home *** CD-ROM | disk | FTP | other *** search
/ Deutsche Edition 1 / Deutsche Edition 1.iso / amok / 081-090 / amok87 / muchmore / src / muchmore.mod next >
Text File  |  1993-11-04  |  86KB  |  2,639 lines

  1. (*---------------------------------------------------------------------------
  2.  :Program.      MuchMore.mod
  3.  :Author.       Fridtjof Siebert
  4.  :Address.      Nobileweg 67, D-7000 Stuttgart 40
  5.  :Shortcut.     [fbs]
  6.  :Copyright.    Freeware
  7.  :Language.     Oberon-2
  8.  :Translator.   Amiga Oberon Compiler v3.01
  9.  :History. V1.0 summer-88: First very slow internal version              [fbs]
  10.  :History. V1.1 24-Sep-88: First published version                       [fbs]
  11.  :History. V1.2 26-Nov-88: Now displays Filelength & Percentage          [fbs]
  12.  :History.      27-Nov-88: Mouse can be used instead of Space / BackSpace[fbs]
  13.  :History. V1.3 29-Apr-89: Strong increase in speed, removed WarpText    [fbs]
  14.  :History.      29-Apr-89: Now supports Numeric Keys (Home,PgUp etc.)    [fbs]
  15.  :History.      29-Apr-89: Now opens Screen as big as gfx.normalDisplay  [fbs]
  16.  :History. V1.4 29/30-Apr-89: Asynchronus loading / displaying. Very nice[fbs]
  17.  :History.      30-Apr-89, 00:33: Removed bugs in Filelength & L-Command [fbs]
  18.  :History.      30-Apr-89, 02:21: Added Find-Command                     [fbs]
  19.  :History.      30-Apr-89, 10:30: Scrolling stops when window is inactive[fbs]
  20.  :History.      01-May-89: Allocates no more unneeded memory for text    [fbs]
  21.  :History.      07-May-89: Allocates even less memory now                [fbs]
  22.  :History.      14-May-89: Removed deadlock-bug with Find-Window         [fbs]
  23.  :History. V1.5 25-May-89: Added print feature                           [fbs]
  24.  :History.      25-May-89: Removed all imports (apart from Arts)         [fbs]
  25.  :History.      26-May-89: inspired by J. Kupfer, I added nk 5 to quit   [fbs]
  26.  :History.      26-May-89: Now handle BS correctly                       [fbs]
  27.  :History. V1.6 02-Jul-89: Now supports several fontstyles and colors    [fbs]
  28.  :History. V1.7 03-Jul-89: Is again as fast as it was with 2 colors      [fbs]
  29.  :History.      03-Jul-89: Now no more crashes when quitting while print [fbs]
  30.  :History.      07-Jul-89: removed bug with texts of length 0            [fbs]
  31.  :History. V1.8 10-Jul-89: small bug in find-command removed             [fbs]
  32.  :History.      10-Jul-89: now found strings are highlighted             [fbs]
  33.  :History.      14-Jul-89: nk0 to display fileinfo                       [fbs]
  34.  :History. V2.0 06-Aug-89: Ported this to OBERON                         [fbs]
  35.  :History.      06-Aug-89: Added ARP-FileRequester                       [fbs]
  36.  :History.      07-Aug-89: Added L - (load new file) Command             [fbs]
  37.  :History. V2.1 03-Sep-89: no more gurus if an r/w error occures         [fbs]
  38.  :History.      03-Sep-89: MM used to execute CSI-Codes backwards. fixed [fbs]
  39.  :History.      03-Sep-89: ping / pong with Shift+Fn / Fn                [fbs]
  40.  :History.      03-Sep-89: new command: goto                             [fbs]
  41.  :History. V2.2 05-Sep-89: will run with any keymapping now              [fbs]
  42.  :History. V2.3 17-Sep-89: New command: sleep & Pop-Up feature           [fbs]
  43.  :History.      17-Sep-89: "MuchMore -s" will go to sleep immediately    [fbs]
  44.  :History.      17-Sep-89: Interprets <CSI>m as <CSI>0m now              [fbs]
  45.  :History. V2.4 17-Sep-89: New command: write block "w"                  [fbs]
  46.  :History.      17-Sep-89: rewritten argument parser to allow quotes     [fbs]
  47.  :History. V2.5 18-Sep-89: now uses the 8x8 font set with SetFont        [fbs]
  48.  :History.      19-Sep-89: no more scatters memory. Allocates 4K Chunks  [fbs]
  49.  :History. V2.6 26-Jun-90: Made MuchMore reentrant                       [fbs]
  50.  :History.      26-Jun-90: Opens 1-Plane Screen if memory is rare        [fbs]
  51.  :History.      26-Jun-90: Asynchronus fast scrolling with Ctrl-Up/Down  [fbs]
  52.  :History.      26-Jun-90: Now supports interlaced screens               [fbs]
  53.  :History.      08-Aug-90: CLI-Option '-l' to toggle interlaced mode     [fbs]
  54.  :History. V2.7 09-Aug-90: no more RethinkDisplay()s,looks good with 2.0 [fbs]
  55.  :History.      10-Aug-90: Supports Kick2.0 ASL-FileRequester            [fbs]
  56.  :History. V2.8 26-Dez-90: Leaves space between lines on interlaced scrns[fbs]
  57.  :History. V3.0 04-Jul-91: Supports any non-proportional font now        [fbs]
  58.  :History.      04-Jul-91: no more supports '-s' (sleep), was rarely used[fbs]
  59.  :History.      04-Jul-91: new Options -f<font> and -s<size> for font    [fbs]
  60.  :History.      09-Nov-91: Find works w/ dmouse (window may get inactive)[fbs]
  61.  :History. V3.1 04-Sep-92: Uses Screenmode of Workbench screen           [fbs]
  62.  :History. V3.2 02-Nov-92: Supports non-scrollable screens               [fbs]
  63.  :History.      02-Nov-92: Complete redraw doesn't scroll anymore        [fbs]
  64.  :History. V3.2.1 24-Dec-92: XPK Support                         (Chr. Stiens)
  65.  :History.      24-Dec-92: New option -p for Password            (Chr. Stiens)
  66.  :History.      24-Dec-92: New option -e for Extra Spacing       (Chr. Stiens)
  67.  :History.      24-Dec-92: New option -c for Screen Colors       (Chr. Stiens)
  68.  :History.      24-Dec-92: Tooltypes                             (Chr. Stiens)
  69.  :History. V3.2.2 08-Jan-93: Doesn't use MyMakeScreen() no more  (Chr. Stiens)
  70.  :History. V3.2.3 08-Feb-93: Now closes Console Device           (Chr. Stiens)
  71.  :History.      08-Feb-93: Non-Scroll Mode didn't work always    (Chr. Stiens)
  72.  :History.      10-Feb-93: ScreenMode Requester                  (Chr. Stiens)
  73.  :History.      10-Feb-93: New Option -s for Scroll Mode         (Chr. Stiens)
  74.  :History.      10-Feb-93: Busy Pointer                          (Chr. Stiens)
  75.  :History.      14-Feb-93: Now evals Tooltypes also on CLI start (Chr. Stiens)
  76.  :History. V3.2.4 15-Feb-93: Clears Idcmp while Busy             (Chr. Stiens)
  77.  :History.      15-Feb-93: Bugs in GetString fixed               (Chr. Stiens)
  78.  :History.      19-Feb-93: More Scrollmodes                      (Chr. Stiens)
  79.  :History.      20-Feb-93: Bug in Type() fixed                   (Chr. Stiens)
  80.  :History. V3.2.5 08-Mar-93: Removed Asynch Scrolling            (Chr. Stiens)
  81.  :History.      08-Mar-93: New Option -t for Taskpri             (Chr. Stiens)
  82.  :History.      10-Mar-93: Now uses Dos.ReadArgs if KS 2.04      (Chr. Stiens)
  83.  :History. V3.2.6 19-Mar-93: scrollmode 3 now also scrolls soft  (Chr. Stiens)
  84.  :History.      19-Mar-93: New Option -o for one plane           (Chr. Stiens)
  85.  :History.      19-Mar-93: New Option -a for tab width           (Chr. Stiens)
  86.  :History.      19-Mar-93: Removed QText                         (Chr. Stiens)
  87.  :History.      21-Mar-93: Opens screen with full overscan width (Chr. Stiens)
  88.  :History.      22-Mar-93: Filename can be on any pos at KS1.3   (Chr. Stiens)
  89.  :History.      27-Mar-93: New Option N=NOOSCAN                  (Chr. Stiens)
  90.  :History. V3.2.7 07-Apr-93: Dont pokes to bitmap no more        (Chr. Stiens)
  91.  :Contents.     A Soft-Scrolling ASCII-File Printer.
  92.  :Remark.       Compile: 'Oberon -[svbcrntz]dma MuchMore'
  93.  :Remark.       Link:    'OLink -dma MuchMore'
  94. ---------------------------------------------------------------------------*)
  95.  
  96.  
  97. MODULE MuchMore; (* $StackChk- *)
  98.  
  99. IMPORT d  := Dos,
  100.        e  := Exec,
  101.        g  := Graphics,
  102.        gt := GadTools,
  103.        I  := Intuition,
  104.        ie := InputEvent,
  105.        str:= Strings,
  106.        u  := Utility,
  107.        ol := OberonLib,
  108.        SYS:= SYSTEM;
  109.  
  110. (*-------------------------------------------------------------------------*)
  111.  
  112. CONST
  113.   oom = "Out of memory!";
  114.   cos = "Can't open screen!";
  115.   cow = "Can't open window!";
  116.   cof = "Can't open file!";
  117.  
  118.   usage = "Usage: MuchMore [-a#|-c#{,#}|-e#|-f<name>/#|-l|-o|-p<name>|-s#|-t#|file]\n"
  119.           "\ta = tab width\n"
  120.           "\tc = colors\n"
  121.           "\te = extra spacing\n"
  122.           "\tf = font/size\n"
  123.           "\tl = toggle lace\n"
  124.           "\to = one plane\n"
  125.           "\tp = password\n"
  126.           "\ts = scroll mode\n"
  127.           "\tt = toolpri";
  128.  
  129.   rwerr = "Read/Write Error";
  130.   noarp = "Need arp for FileReq";
  131.  
  132.   conerr = "Console problem";
  133.   MuchText = "MuchMore V3.2.7 © 1993 AMOK\o$VER: muchmore 3.27 (7.4.93)";
  134.   w = TRUE;
  135.   f = FALSE;
  136.   MaxLen = 256;
  137.  
  138.   MyIdcmp = LONGSET{I.inactiveWindow,I.activeWindow,I.rawKey,I.mouseButtons};
  139.  
  140. (* Control codes: *)
  141.   plain    = CHR(17);
  142.   italic   = CHR(18);
  143.   bold     = CHR(19);
  144.   boldit   = CHR(20);
  145.   ulineon  = CHR(21);
  146.   ulineoff = CHR(22);
  147.  
  148.   Italic = 0;
  149.   Bold   = 1;
  150.   Ulin   = 2;
  151.   Inv    = 3;
  152.  
  153.   saInterleaved = I.saDummy + 00022H;
  154.  
  155.  
  156. TYPE
  157.   String    = e.STRING;
  158.   StringPtr = e.STRPTR;
  159.   CharPtr   = UNTRACED POINTER TO CHAR;
  160.  
  161.   TextLinePtr = UNTRACED POINTER TO TextLine;
  162.   TextLine = STRUCT
  163.                prev,
  164.                next : TextLinePtr;
  165.                len  : INTEGER;
  166.                size : INTEGER;
  167.                text : String;
  168.              END;
  169.  
  170. TYPE
  171.   FileRequesterPtr = UNTRACED POINTER TO FileRequester;
  172.   FileRequester = STRUCT
  173.                     hail      : StringPtr;
  174.                     ddef      : StringPtr;
  175.                     ddir      : StringPtr;
  176.                     wind      : I.WindowPtr;
  177.                     funcFlags : SHORTSET;
  178.                     flags2    : SHORTSET;
  179.                     function  : PROCEDURE;
  180.                     reserved2 : LONGINT;
  181.                   END;
  182.  
  183.   WBStartupPtr = UNTRACED POINTER TO STRUCT (message : e.Message)
  184.                    process    : d.ProcessId;
  185.                    segment    : e.BPTR;
  186.                    numArgs    : LONGINT;
  187.                    toolWindow : StringPtr;
  188.                    argList : UNTRACED POINTER TO ARRAY 256 OF STRUCT
  189.                                  lock : d.FileLockPtr;
  190.                                  name : StringPtr;
  191.                              END;
  192.                  END;
  193.  
  194.   DiskObjectPtr = UNTRACED POINTER TO STRUCT
  195.                     magic      : INTEGER;
  196.                     version    : INTEGER;
  197.                     gadget     : I.Gadget;
  198.                     type       : SHORTINT;
  199.                     defaultTool: StringPtr;
  200.                     toolTypes  : e.APTR;
  201.                     currentX   : LONGINT;
  202.                     currentY   : LONGINT;
  203.                     drawerData : e.APTR;
  204.                     toolWindow : StringPtr;
  205.                     stackSize  : LONGINT;
  206.                   END;
  207.  
  208.   LongPtr = UNTRACED POINTER TO LONGINT;
  209.  
  210.   Args = STRUCT
  211.            a : LongPtr;
  212.            c : StringPtr;
  213.            d : StringPtr;
  214.            e : LongPtr;
  215.            f : StringPtr;
  216.            n : StringPtr;
  217.            o : StringPtr;
  218.            p : StringPtr;
  219.            s : LongPtr;
  220.            t : LongPtr;
  221.            file : StringPtr;
  222.          END;
  223.  
  224. VAR
  225.   pub: I.ScreenPtr;              (* default public screen             *)
  226.   Screen: I.ScreenPtr;           (* Screen that contains the Text     *)
  227.   rp: g.RastPortPtr;             (* Screen's RastPort                 *)
  228.   id: LONGINT;                   (* Display ID                        *)
  229.   BM: g.BitMapPtr;               (* Screen's BitMap                   *)
  230.   Window: I.WindowPtr;           (* My window                         *)
  231.   win: I.WindowPtr;              (* window for Find & Goto            *)
  232.   MyFile: d.FileHandlePtr;       (* For loading Textfile              *)
  233.   MyAttr: g.TextAttr;            (* The selected Font attributes      *)
  234.   MyFont: g.TextFontPtr;         (* The selected Font                 *)
  235.   FontName: String;              (* My Font Name or ""                *)
  236.   FontSize: INTEGER;             (* My Font Size                      *)
  237.   FirstLine: TextLinePtr;        (* the topmost Line                  *)
  238.   TopLine: TextLinePtr;          (* the topmost Line                  *)
  239.   BottomLine: TextLinePtr;       (* Last Line displayed on Screen     *)
  240.   LoadLine: TextLinePtr;         (* currently loaded Line             *)
  241.   LastLine: TextLinePtr;         (* Last element of LineList          *)
  242.   Name,OldName: String;          (* Text's Name                       *)
  243.   option: String;                (* CLI Option                        *)
  244.   taskpri,oldpri: SHORTINT;      (* Muchmore's Task Priority          *)
  245.   Pens: String;                  (* Screen colors                     *)
  246.   Cols: ARRAY 4 OF INTEGER;      (* Color array for LoadRGB4          *)
  247.   icon: DiskObjectPtr;           (* .info                             *)
  248.   nameptr: StringPtr;            (* String Pointer                    *)
  249.   chptr: CharPtr;                (* Char Pointer                      *)
  250.   PStr: String;                  (* The command for Dos.Execute       *)
  251.   Buffer: ARRAY 512 OF CHAR;     (* Buffer for Reading                *)
  252.   RQPos: LONGINT;                (* Position within ReadBuffer        *)
  253.   RQLen: LONGINT;                (* Number of CHARs in Buffer         *)
  254.   scrollmode: INTEGER;           (* 0=MakeScreen/MrgCop 1=ScrollVPort *)
  255.   NumLines: INTEGER;             (* Number of Lines on Screen         *)
  256.   fontWidth,fontHeight: INTEGER; (* Font size                         *)
  257.   fontBaseLine: INTEGER;         (* Font base line                    *)
  258.   spacing: INTEGER;              (* Extra Line Spacing                *)
  259.   NumColumns: INTEGER;           (* Number of Columns on Screen       *)
  260.   PageSize: LONGINT;             (* fontHeight*NumLines*NumColumns    *)
  261.   PageHeight: INTEGER;           (* fontHeight*NumLines               *)
  262.   LineSize: LONGINT;             (* fontHeight*NumColumns             *)
  263.   AnzLines: LONGINT;             (* Length of Text in Lines           *)
  264.   MyLock,OldDir: d.FileLockPtr;  (* To Examine and Load File          *)
  265.   oldcd: d.FileLockPtr;          (* To save old CD                    *)
  266.   FileInfo: d.FileInfoBlock;     (* to get File's length              *)
  267.   FileLength,TextLength: LONGINT;(* Length of File and Displayed Text *)
  268.   ScreenPos: INTEGER;            (* actual position within bitmap     *)
  269.   ShowTask: e.Task;              (* the task that displays the text   *)
  270.   ShowStack: ARRAY 1024 OF LONGINT; (* it's stack                     *)
  271.   ShowTaskRunning: BOOLEAN;      (* is Showtask activated?            *)
  272.   SignalNewData: BOOLEAN;        (* Signal when new data is loaded    *)
  273.   SignalAllRead: BOOLEAN;        (* send signal at end of text        *)
  274.   Done: BOOLEAN;                 (* Quit                              *)
  275.   print: BOOLEAN;                (* print text                        *)
  276.   NewText: BOOLEAN;              (* load new text                     *)
  277.   Info: BOOLEAN;                 (* is info currently displayed ?     *)
  278.   modeReq: BOOLEAN;              (* Show Display Mode Requester?      *)
  279.   onePlane: BOOLEAN;             (* Only one Bitplane?                *)
  280.   Scroll: BOOLEAN;               (* scrolling or waiting?             *)
  281.   Fast: BOOLEAN;                 (* scrollquick?                      *)
  282.   Sync: BOOLEAN;                 (* scroll very quick?                *)
  283.   lace,oldLace: BOOLEAN;         (* use interlaced screen?            *)
  284.   Decrunched: BOOLEAN;           (* Is file decrunched?               *)
  285.   Scrollable: BOOLEAN;           (* is screen able to scroll?         *)
  286.   noOscan: BOOLEAN;              (* Open Text-overscan Screen?        *)
  287.   overscanTag: LONGINT;          (* overscan tag                      *)
  288.   mySigBit: INTEGER;             (* My SignalBit                      *)
  289.   mySig: LONGSET;                (* My SignalSet = LONGSET{mySigBit}  *)
  290.   Me: d.ProcessPtr;              (* my main task                      *)
  291.   MyMsgPtr: I.IntuiMessagePtr;   (* for receiving Messages            *)
  292.   i,j: INTEGER;                  (* count                             *)
  293.   frame: INTEGER;                (* Frame Count                       *)
  294.   in,out: d.FileHandlePtr;       (* i/o for TYPE xxx TO PRT:          *)
  295.   fg,bg: INTEGER;                (* Text colors                       *)
  296.   style: SHORTSET;               (* Text style                        *)
  297.   CommLine: UNTRACED POINTER TO ARRAY 1000 OF CHAR;(* The CLI-commands*)
  298.   tabw: INTEGER;                 (* Tabulator width                   *)
  299.   rd: d.RDArgsPtr;               (* For ReadArgs                      *)
  300.   args: Args;                    (* My CLI Args                       *)
  301.   ArgPtr: StringPtr;              (* to get WBArg                      *)
  302.   wbm: WBStartupPtr;             (* WBenchMessage                     *)
  303.   ri: g.RasInfoPtr;              (* Screen's ViewPort's RasInfo       *)
  304.   NuScreen: I.NewScreen;         (* to open screen                    *)
  305.   dims: g.DimensionInfo;         (* Dims for KS2.0                    *)
  306.   disp: g.DisplayInfo;           (* DisplayInfo for KS2.0             *)
  307.   NuWindow: I.NewWindow;         (* to open window                    *)
  308.   Prefs: I.Preferences;          (* Preferences (need wbLace)         *)
  309.   StrGadget: I.Gadget;           (* Gadget for Find-Command           *)
  310.   StrInfo: I.StringInfo;         (* its special info                  *)
  311.   arp: e.LibraryPtr;             (* ArpBase                           *)
  312.   asl: e.LibraryPtr;             (* ASL-librarybase                   *)
  313.   diskFontBase : e.LibraryPtr;   (* DiskFont-LibraryBase              *)
  314.   xpk: e.LibraryPtr;             (* XpkMaster-Librarybase             *)
  315.   iconBase: e.LibraryPtr;        (* Icon-Librarybase                  *)
  316.   body,text,ok: I.IntuiText;     (* IntuiTexts for AutoRequest        *)
  317.   FR: FileRequester;             (* The Requester                     *)
  318.   Filename: String;              (* The Filename (without path)       *)
  319.   Dirname: String;               (* its path                          *)
  320.   Pattern: ARRAY 80 OF CHAR;     (* The pattern for Filerequester     *)
  321.   Password: String;              (* Password for encrypted texts      *)
  322.   NewDisp: BOOLEAN;              (* need to rebuild Display ?         *)
  323.   TextMarkers: ARRAY 10 OF TextLinePtr; (* Marked Positions in text   *)
  324.   FindLine: TextLinePtr;         (* Last found line                   *)
  325.   KeyMap: ARRAY 50H OF CHAR;     (* console's KeyMap                  *)
  326.   wreq: e.IOStdReq;              (* Console IO-Request                *)
  327.   console: e.DevicePtr;          (* the console.device                *)
  328.   ievent: ie.InputEvent;         (* InputEvent to convert keycodes    *)
  329.   WriteName: String;             (* File to write Block               *)
  330.   savefrom,savesize: LONGINT;    (* How much to save?                 *)
  331.   save: BOOLEAN;                 (* save block                        *)
  332.   buffer: UNTRACED POINTER TO LONGINT; (* buffer to save file         *)
  333.   c: CHAR;                       (* \ used by GetTextLine();          *)
  334.   le: INTEGER;                   (* / global for speed                *)
  335.  
  336. (*------  Memory:  ------*)
  337.  
  338. CONST ChunkSize = 16384;          (* size of allocated chunks *)
  339.  
  340. TYPE
  341.   MemChunkPtr = UNTRACED POINTER TO MemChunk;  (* chunklist *)
  342.   MemChunk = STRUCT
  343.                prev: MemChunkPtr;     (* link *)
  344.                data: ARRAY ChunkSize OF SYS.BYTE; (* ChunkSize Bytes of memory *)
  345.              END;
  346.  
  347. VAR
  348.   MemIndex: INTEGER;      (* index in current Chunk *)
  349.   CurChunk: MemChunkPtr;  (* current chunk          *)
  350.  
  351.  
  352. (*-------------------------------------------------------------------------*)
  353.  
  354. (*------  Console Procedure:  ------*)
  355.  
  356. PROCEDURE RawKeyConvert{console,-48}(events{8}:ie.InputEventPtr;
  357.                                      buffer{9}:LONGINT;
  358.                                      length{1}:LONGINT;
  359.                                      keyMap{10}:LONGINT);
  360.  
  361.  
  362. (*-------------------------------------------------------------------------*)
  363.  
  364. (*------  DiskFont Procedure:  ------*)
  365.  
  366. PROCEDURE OpenDiskFont*{diskFontBase,-30}(VAR textAttr{8}: g.TextAttr): g.TextFontPtr;
  367.  
  368.  
  369. (*-------------------------------------------------------------------------*)
  370.  
  371. (*------  Icon Procedures:  ------*)
  372.  
  373. PROCEDURE GetDiskObject {iconBase,- 78}(name{8}        : ARRAY OF CHAR): DiskObjectPtr;
  374. PROCEDURE FreeDiskObject{iconBase,- 90}(diskobj{8}     : DiskObjectPtr);
  375. PROCEDURE FindToolType  {iconBase,- 96}(toolTypes{8}   : e.APTR;
  376.                                         typeName{9}    : ARRAY OF CHAR): StringPtr;
  377. PROCEDURE MatchToolValue{iconBase,-102}(typeString{8}  : ARRAY OF CHAR;
  378.                                         val{9}         : ARRAY OF CHAR): BOOLEAN;
  379.  
  380.  
  381. (*-------------------------------------------------------------------------*)
  382.  
  383.  
  384. PROCEDURE Append(VAR s1: String; s2: StringPtr);
  385. (* appends s2 to s1 *)
  386. VAR p,q: INTEGER;
  387. BEGIN
  388.   p := SHORT(str.Length(s1)); q := 0;
  389.   WHILE (p<SIZE(s1)) & (s2^[q]#0X) & (p<NumColumns) DO
  390.     s1[p] := s2^[q]; INC(p); INC(q)
  391.   END;
  392.   IF p<SIZE(s1) THEN s1[p] := 0X END;
  393. END Append;
  394.  
  395.  
  396. (*-----------------------------  Requester:  ------------------------------*)
  397.  
  398.  
  399. PROCEDURE Request(Text: ARRAY OF CHAR); (* $CopyArrays- *)
  400.  
  401. VAR
  402.   out: d.FileHandlePtr;
  403.   c: CHAR;
  404.  
  405. BEGIN
  406.   IF ol.wbStarted THEN
  407.     body.frontPen := 0; body.backPen  := 1;  body.drawMode := g.jam2;
  408.     body.leftEdge := 12; body.topEdge  := 8;
  409.     text := body; ok := body;
  410.     body.iText    := SYS.ADR(MuchText);
  411.     body.nextText := SYS.ADR(text);
  412.     text.iText    := SYS.ADR(Text); text.topEdge := 22;
  413.     ok.leftEdge   := 6; ok.topEdge := 3; ok.iText := SYS.ADR("  OK  ");
  414.     SYS.SETREG(0,I.AutoRequest(NIL,SYS.ADR(body),NIL,SYS.ADR(ok),LONGSET{I.rawKey},LONGSET{},320,65));
  415.   ELSE
  416.     out := d.Output();
  417.     SYS.SETREG(0,d.Write(out,Text,str.Length(Text)));
  418.     c := 0AX;
  419.     SYS.SETREG(0,d.Write(out,c,1));
  420.   END;
  421.   HALT(0);
  422. END Request;
  423.  
  424.  
  425. PROCEDURE OutOfMemHandler;
  426. CONST ES = I.EasyStruct(SIZE(I.EasyStruct),LONGSET{},
  427.                         SYS.ADR(MuchText),
  428.                         SYS.ADR(oom),
  429.                         SYS.ADR("Retry|Abort"));
  430. BEGIN
  431.   IF I.int.libNode.version >= 37 THEN
  432.     IF I.EasyRequest(NIL,SYS.ADR(ES),NIL,NIL)=0 THEN
  433.       HALT(0)
  434.     END;
  435.   ELSE
  436.     Request(oom);
  437.   END;
  438. END OutOfMemHandler;
  439.  
  440.  
  441. (*-------------------------------------------------------------------------*)
  442.  
  443.  
  444. PROCEDURE AllocLine(sz: INTEGER): TextLinePtr;
  445.  
  446. VAR
  447.   a: TextLinePtr;
  448.   newchunk: MemChunkPtr;
  449.  
  450. BEGIN
  451.   INC(sz,SIZE(TextLine)-MaxLen); IF ODD(sz) THEN INC(sz) END;
  452.   IF MemIndex+sz<=ChunkSize THEN     (* does mem fit into current chunk ? *)
  453.     INC(MemIndex,sz);                (* increment index in current chunk  *)
  454.   ELSE
  455.     NEW(newchunk);                   (* allocate new chunk                *)
  456.     newchunk.prev := CurChunk;       (* link chunk into list              *)
  457.     CurChunk := newchunk;
  458.     MemIndex := sz;
  459.   END;
  460.   RETURN SYS.ADR(CurChunk.data[MemIndex-sz]);
  461. END AllocLine;
  462.  
  463.  
  464. PROCEDURE DisposeLines();
  465.  
  466. VAR chunk: MemChunkPtr;
  467.  
  468. BEGIN
  469.   WHILE CurChunk#NIL DO
  470.     chunk := CurChunk.prev;
  471.     DISPOSE(CurChunk);
  472.     CurChunk := chunk;
  473.   END;
  474.   MemIndex := ChunkSize;
  475. END DisposeLines;
  476.  
  477.  
  478. (*-------------------------------------------------------------------------*)
  479.  
  480. (* $Debug- *)
  481.  
  482.  
  483. PROCEDURE Busy;
  484.  
  485. (* $DataChip+ *)
  486.  
  487. TYPE Data = ARRAY 36 OF INTEGER;
  488.  
  489. CONST ClockData = Data(
  490.   00000U,00000U,
  491.   00400U,007C0U, 00000U,007C0U, 00100U,00380U, 00000U,007E0U,
  492.   007C0U,01FF8U, 01FF0U,03FECU, 03FF8U,07FDEU, 03FF8U,07FBEU,
  493.   07FFCU,0FF7FU, 07EFCU,0FFFFU, 07FFCU,0FFFFU, 03FF8U,07FFEU,
  494.   03FF8U,07FFEU, 01FF0U,03FFCU, 007C0U,01FF8U, 00000U,007E0U,
  495.   00000U,00000U);
  496.  
  497. BEGIN
  498.   IF Window#NIL THEN
  499.     I.OldModifyIDCMP(Window,MyIdcmp-LONGSET{I.rawKey,I.mouseButtons});
  500.     I.SetPointer(Window,ClockData,16,16,-6,0);
  501.   END;
  502. END Busy;
  503.  
  504.  
  505. PROCEDURE UnBusy;
  506. BEGIN
  507.   IF Window#NIL THEN
  508.     I.ClearPointer(Window);
  509.     I.OldModifyIDCMP(Window,MyIdcmp);
  510.   END;
  511. END UnBusy;
  512.  
  513.  
  514. (*------  Scroll:  ------*)
  515.  
  516. PROCEDURE MakeThink(sync,fast,always: BOOLEAN);
  517. VAR m: INTEGER;
  518.  
  519. BEGIN
  520.   IF Scrollable THEN
  521.     m := 1;
  522.     IF ~always THEN
  523.       IF lace & ~fast THEN m := 2 END;
  524.       IF ~sync THEN INC(m,m*2) END;
  525.     END;
  526.     IF (m=1) OR (frame MOD m=0) THEN
  527.       CASE scrollmode OF
  528.       | 0: I.MakeScreen(Screen);
  529.            e.Forbid; g.MrgCop(I.ViewAddress()); e.Permit;
  530.            g.WaitTOF;
  531.       | 1: g.ScrollVPort(SYS.ADR(Screen.viewPort));
  532.            g.WaitTOF;
  533.       ELSE
  534.            I.MakeScreen(Screen);
  535.            I.RethinkDisplay();
  536.       END;
  537.     END;
  538.     INC(frame);
  539.   END;
  540. END MakeThink;
  541.  
  542.  
  543. (*------  Clear Display:  ------*)
  544.  
  545.  
  546. PROCEDURE ClearBitMaps;
  547. VAR i: INTEGER;
  548.  
  549. BEGIN
  550.   g.SetRast(rp,0);
  551.   IF Scrollable THEN
  552.     ri.ryOffset := 0;
  553.     ScreenPos := 0;
  554.     MakeThink(f,f,w);
  555.   END;
  556. END ClearBitMaps;
  557.  
  558. (*-------------------------------------------------------------------------*)
  559.  
  560. (*------  Read one TextLine into a Variable:  ------*)
  561.  
  562.  
  563. PROCEDURE GetTextLine(): TextLinePtr;
  564. (* returns NIL at EOF *)
  565.  
  566. VAR
  567.   l: TextLinePtr;
  568.   sz,wd,i,j: INTEGER;
  569.   txt: ARRAY MaxLen+1 OF CHAR;
  570.   num: ARRAY 10 OF INTEGER;
  571.   newcol: BOOLEAN;
  572.   oldstyle: SHORTSET;
  573.  
  574.   PROCEDURE GetCh();
  575.  
  576.   BEGIN
  577.     IF RQPos=RQLen THEN
  578.       RQLen := d.Read(MyFile,Buffer,SIZE(Buffer));
  579.       IF RQLen<0 THEN Request(rwerr) END;
  580.       RQPos := 0;
  581.     END;
  582.     IF RQLen=0 THEN c := 0X ELSE
  583.       c := Buffer[RQPos]; IF c=0X THEN c:=1X END;
  584.       INC(RQPos); INC(le);
  585.     END;
  586.   END GetCh;
  587.  
  588. BEGIN
  589.   IF RQLen=0 THEN RETURN NIL END;
  590.   sz := 0; wd := 0; le := 0;
  591.   IF Italic IN style THEN IF Bold IN style THEN txt[sz] := boldit ELSE txt[sz] := italic END; INC(sz)
  592.                      ELSE IF Bold IN style THEN txt[sz] := bold; INC(sz) END                      END;
  593.   IF   Ulin IN style     THEN txt[sz] := ulineon; INC(sz) END;
  594.   IF    Inv IN style     THEN txt[sz] := CHR(fg+4*bg+1); INC(sz)
  595.   ELSIF (fg#1) OR (bg#0) THEN txt[sz] := CHR(bg+4*fg+1); INC(sz) END;
  596.   LOOP
  597.     LOOP
  598.       GetCh;
  599.       IF SYS.VAL(CHAR,SYS.VAL(SHORTSET,c)*SHORTSET{0..6})#1BX THEN EXIT END;
  600.       i := -1;
  601.       REPEAT
  602.         GetCh;
  603.         IF (c>=30X) & (c<=39X) THEN
  604.           INC(i); num[i] := 0;
  605.           REPEAT
  606.             num[i] := 10*num[i]+ORD(c)-ORD(30X); GetCh;
  607.           UNTIL (c<30X) OR (c>39X);
  608.         END;
  609.         c := CAP(c);
  610.       UNTIL (c>=3FX(*"?"*)) & (c<=5AX) OR (c=0X) OR (i=9);
  611.       IF c=4DX THEN
  612.         newcol := f; oldstyle := style; j := 0;
  613.         IF i=-1 THEN i:=0; num[0] := 0 END;
  614.         WHILE (i>=j) & (sz<MaxLen-1) DO
  615.           CASE num[j] OF
  616.           0: style := SHORTSET{}; fg := 1; bg := 0; newcol := w |
  617.           1: INCL(style,Bold) |
  618.           2: fg := 2; IF onePlane THEN fg := 1 END; newcol := w (* I hope this is correct *) |
  619.           3: INCL(style,Italic) |
  620.           4: INCL(style,Ulin) |
  621.           7: INCL(style,Inv); newcol := w |
  622.           30..37: fg := (num[j]-30) MOD 4; IF onePlane & (fg>1) THEN fg:=1 END; newcol := w |
  623.           40..47: bg := (num[j]-40) MOD 4; IF onePlane & (bg>1) THEN bg:=1 END; newcol := w |
  624.           ELSE END;
  625.           INC(j);
  626.         END;
  627.         IF (oldstyle#style) & (sz<MaxLen) THEN
  628.           IF Italic IN style THEN IF Bold IN style THEN txt[sz] := boldit ELSE txt[sz] := italic END;
  629.                              ELSE IF Bold IN style THEN txt[sz] := bold   ELSE txt[sz] := plain  END;
  630.           END;
  631.           INC(sz);
  632.           IF (Ulin IN style) THEN
  633.             IF ~((Ulin IN oldstyle)) & (sz<MaxLen) THEN
  634.               txt[sz] := ulineon;
  635.               INC(sz);
  636.             END;
  637.           ELSE
  638.             IF (Ulin IN oldstyle) & (sz<MaxLen) THEN
  639.               txt[sz] := ulineoff;
  640.               INC(sz);
  641.             END;
  642.           END;
  643.         END;
  644.         IF newcol & (sz<MaxLen) THEN
  645.           IF Inv IN style THEN txt[sz] := CHR(fg+4*bg+1)
  646.                           ELSE txt[sz] := CHR(bg+4*fg+1) END;
  647.           INC(sz);
  648.         END;
  649.       END;   (* IF c="m" THEN *)
  650.     END;   (* LOOP *)
  651.     CASE c OF
  652.      20X.. 7FX:    txt[sz] := c; INC(sz); INC(wd) |
  653.     0A1X..0FFX:    txt[sz] := c; INC(sz); INC(wd) |
  654.     8X: (* BS *)   IF wd>0 THEN DEC(sz); DEC(wd); END |
  655.     9X: (* TAB *)
  656.       REPEAT
  657.         txt[sz] := 20X; INC(sz); INC(wd)
  658.       UNTIL (sz=MaxLen) OR (wd=NumColumns) OR (sz MOD tabw=0) |
  659.     0A0X:                txt[sz] := 20X; INC(sz); INC(wd) |
  660.     0AX,0X,0CX: EXIT |
  661.     ELSE END;
  662.     IF (wd>=NumColumns) OR (sz>=MaxLen) THEN EXIT END;
  663.   END;
  664.   txt[sz] := 0X; INC(sz);
  665.   l := AllocLine(sz);
  666.   l.len := le; l.size:= sz;
  667.   WHILE sz>0 DO DEC(sz); l.text[sz]:=txt[sz] END;
  668.   RETURN l;
  669. END GetTextLine;
  670.  
  671.  
  672. (*------  Write Line to Screen:  ------*)
  673.  
  674.  
  675. PROCEDURE Type(pos: INTEGER; line: TextLinePtr);
  676.  
  677. VAR
  678.   style: SHORTSET;
  679.   front,back: SHORTINT;
  680.   c: CHAR;
  681.   last,i,x: INTEGER;
  682.   strPtr: UNTRACED POINTER TO ARRAY 256 OF CHAR;
  683.  
  684. BEGIN
  685.   g.SetDrMd(rp,g.jam2);
  686.   IF Scrollable THEN
  687.     i := NuScreen.depth;
  688.     REPEAT
  689.       DEC(i);
  690.       g.BltClear(SYS.VAL(e.APTR,SYS.VAL(LONGINT,BM.planes[i])+pos*LineSize),LineSize,LONGSET{});
  691.     UNTIL i=0;
  692.   END;
  693.   i := 0; x := 0; style := SHORTSET{}; front := 1; back := 0;
  694.   LOOP
  695.     WHILE line.text[i]<" " DO
  696.       c := line.text[i];
  697.       IF c=0X THEN EXIT END;
  698.       CASE c OF
  699.       plain   : style := style - SHORTSET{g.bold,g.italic} |
  700.       italic  : EXCL(style,g.bold); INCL(style,g.italic)   |
  701.       bold    : INCL(style,g.bold); EXCL(style,g.italic)   |
  702.       boldit  : style := style + SHORTSET{g.bold,g.italic} |
  703.       ulineon : INCL(style,g.underlined) |
  704.       ulineoff: EXCL(style,g.underlined) |
  705.       1X..10X : DEC(c);
  706.                 front := SHORT(ORD(c)) DIV 4;
  707.                 back  := SHORT(ORD(c)) MOD 4 |
  708.       ELSE END;
  709.       INC(i);
  710.     END;
  711.     strPtr := SYS.ADR(line.text[i]); last := i;
  712.     REPEAT INC(i) UNTIL line.text[i]<" ";
  713.     SYS.SETREG(0,g.SetSoftStyle(rp,style,-SHORTSET{}));
  714.     g.SetAPen(rp,front);
  715.     g.SetBPen(rp,back);
  716.     g.Move(rp,fontWidth*x,fontHeight*pos+fontBaseLine);
  717.     g.Text(rp,strPtr^,i-last);
  718.     INC(x,i-last);
  719.   END;
  720. END Type;
  721.  
  722.  
  723. PROCEDURE CopyScrollLine(pos: INTEGER);
  724. (* Kopiert die an pos geschriebene Zeile auf den entsprechenden DoubleBuffer-Bereich *)
  725. (*
  726.  * ACHTUNG: Darf nur aufgerufen werden, wenn Scrollable TRUE ist!
  727.  *)
  728.  
  729. VAR
  730.   y,z: INTEGER;
  731.  
  732. BEGIN
  733.   y := pos*fontHeight;
  734.   z := PageHeight;
  735.   IF pos>=NumLines THEN z := -z END;
  736.  
  737.   SYS.SETREG(0,g.BltBitMap(BM, 0,y, BM, 0,y+z, NuScreen.width,fontHeight, 0C0X, SHORTSET{0..7}, NIL));
  738. END CopyScrollLine;
  739.  
  740.  
  741. (*------  Write String to Screen (as bottom line):  ------*)
  742.  
  743.  
  744. VAR writeText: TextLine;
  745.  
  746. PROCEDURE CopyToWriteText(String: StringPtr);
  747. BEGIN
  748.   writeText := FirstLine^;
  749.   i := SHORT(str.Length(String^));
  750.   IF i>=NumColumns THEN i := NumColumns-1 END;
  751.   writeText.text[i+1] := 0X;
  752.   writeText.size := i;
  753.   REPEAT
  754.     writeText.text[i] := String[i];
  755.     DEC(i)
  756.   UNTIL i<0;
  757. END CopyToWriteText;
  758.  
  759.  
  760. (*------  Write String to Screen (at any position):  ------*)
  761.  
  762.  
  763. PROCEDURE TypeTo(VAR text: TextLine; pos: INTEGER);
  764.  
  765. BEGIN
  766.   IF pos<NumLines THEN
  767.     IF ~Scrollable THEN
  768.       Type(pos,SYS.ADR(text));
  769.     ELSE
  770.       INC(pos,ScreenPos);
  771.       Type(pos,SYS.ADR(text));
  772.       CopyScrollLine(pos);
  773.     END;
  774.   END;
  775. END TypeTo;
  776.  
  777.  
  778. (*------  Write String to Screen (at any position):  ------*)
  779.  
  780.  
  781. PROCEDURE WriteTo(String: StringPtr; pos: INTEGER);
  782.  
  783. BEGIN
  784.   CopyToWriteText(String);
  785.   TypeTo(writeText,pos);
  786. END WriteTo;
  787.  
  788.  
  789. (*------  Write Line at Bottom of Text:  ------*)
  790.  
  791.  
  792. PROCEDURE AddBottomLine(Line: TextLinePtr; Fast: BOOLEAN);
  793.  
  794. VAR
  795.   i,j: INTEGER;
  796.   y: INTEGER;
  797.  
  798. BEGIN
  799.   IF ~Scrollable THEN
  800.     g.SetAPen(rp,0); g.SetBPen(rp,0);
  801.     IF Fast THEN
  802.       g.ScrollRaster(rp,0,fontHeight,0,0,NuScreen.width-1,NuScreen.height-1);
  803.       IF Sync THEN g.WaitTOF END;
  804.     ELSE
  805.       i := fontHeight;
  806.       REPEAT
  807.         g.ScrollRaster(rp,0,1,0,0,NuScreen.width-1,NuScreen.height-1);
  808.         IF Sync THEN g.WaitTOF END;
  809.         DEC(i);
  810.       UNTIL i=0;
  811.     END;
  812.     Type(NumLines-1,Line);
  813.   ELSE
  814.     Type(ScreenPos+NumLines,Line);
  815.     y := ScreenPos*fontHeight;
  816.     IF Fast THEN
  817.       INC(ri.ryOffset,fontHeight);
  818.       MakeThink(Sync,w,f);
  819.       SYS.SETREG(0,g.BltBitMap(BM, 0,y+PageHeight, BM, 0,y, NuScreen.width,fontHeight, 0C0X, SHORTSET{0..7}, NIL));
  820.     ELSE
  821.       i := fontHeight;
  822.       REPEAT
  823.         INC(ri.ryOffset);
  824.         MakeThink(Sync,f,f);
  825.         SYS.SETREG(0,g.BltBitMap(BM, 0,y+PageHeight, BM, 0,y, NuScreen.width,1, 0C0X, SHORTSET{0..7}, NIL));
  826.         INC(y);
  827.         DEC(i);
  828.       UNTIL i=0;
  829.     END;
  830.     INC(ScreenPos);
  831.     IF ScreenPos=NumLines THEN
  832.       ScreenPos := 0;
  833.       ri.ryOffset := 0;
  834.     END;
  835.   END;
  836. END AddBottomLine;
  837.  
  838.  
  839. (*------  Check whether BottomLine.next is NIL or not:  ------*)
  840.  
  841.  
  842. PROCEDURE TryBottomnext(): BOOLEAN;
  843. (* returns TRUE if BottomLine.next#NIL END; *)
  844.  
  845. BEGIN
  846.   IF (BottomLine.next=NIL) & (MyFile#NIL) THEN
  847.     SignalNewData := w;
  848.     SYS.SETREG(0,e.Wait(mySig));
  849.     SignalNewData := f;
  850.   END;
  851.   RETURN BottomLine.next#NIL;
  852. END TryBottomnext;
  853.  
  854.  
  855. (*------  Scroll down one Line:  ------*)
  856.  
  857.  
  858. PROCEDURE ScrollDown(Fast: BOOLEAN);
  859.  
  860. BEGIN
  861.   IF TryBottomnext() THEN
  862.     BottomLine := BottomLine.next;
  863.     INC(AnzLines);
  864.     INC(TextLength,BottomLine.len);
  865.   ELSE RETURN END;
  866.   IF AnzLines>=NumLines THEN TopLine := TopLine.next END;
  867.   AddBottomLine(BottomLine,Fast);
  868. END ScrollDown;
  869.  
  870.  
  871. (*------  Scroll Up one Line:  ------*)
  872.  
  873.  
  874. PROCEDURE ScrollUp(Fast: BOOLEAN);
  875.  
  876. VAR
  877.   i,j: INTEGER;
  878.   y: INTEGER;
  879.  
  880. BEGIN
  881.   IF (TopLine.prev#NIL) & (TopLine.prev.prev#NIL) THEN
  882.     TopLine := TopLine.prev;
  883.     DEC(TextLength,BottomLine.len);
  884.     DEC(AnzLines);
  885.     BottomLine := BottomLine.prev;
  886.     IF ~Scrollable THEN
  887.       g.SetAPen(rp,0); g.SetBPen(rp,0);
  888.       IF Fast THEN
  889.         g.ScrollRaster(rp,0,-fontHeight,0,0,NuScreen.width-1,NuScreen.height-1);
  890.         IF Sync THEN g.WaitTOF END;
  891.       ELSE
  892.         i := fontHeight;
  893.         REPEAT
  894.           g.ScrollRaster(rp,0,-1,0,0,NuScreen.width-1,NuScreen.height-1);
  895.           IF Sync THEN g.WaitTOF END;
  896.           DEC(i)
  897.         UNTIL i=0;
  898.       END;
  899.       Type(0,TopLine.prev);
  900.     ELSE
  901.       IF ScreenPos=0 THEN
  902.         ri.ryOffset  := NumLines*fontHeight;
  903.         ScreenPos := NumLines-1;
  904.       ELSE
  905.         DEC(ScreenPos);
  906.       END;
  907.       Type(ScreenPos,TopLine.prev);
  908.       y := ScreenPos*fontHeight;
  909.       IF Fast THEN
  910.         DEC(ri.ryOffset,fontHeight);
  911.         MakeThink(Sync,w,f);
  912.         SYS.SETREG(0,g.BltBitMap(BM, 0,y, BM, 0,y+PageHeight, NuScreen.width,fontHeight, 0C0X, SHORTSET{0..7}, NIL));
  913.       ELSE
  914.         INC(y,fontHeight);
  915.         i := fontHeight;
  916.         REPEAT
  917.           DEC(ri.ryOffset);
  918.           MakeThink(Sync,f,f);
  919.           DEC(y);
  920.           SYS.SETREG(0,g.BltBitMap(BM, 0,y, BM, 0,y+PageHeight, NuScreen.width,1, 0C0X, SHORTSET{0..7}, NIL));
  921.           DEC(i);
  922.         UNTIL i=0;
  923.       END;
  924.     END;
  925.   END;   (* IF TopLine#NIL ... *)
  926. END ScrollUp;
  927.  
  928.  
  929. (*------  Undo last AddBottomLine:  ------*)
  930.  
  931.  
  932. PROCEDURE DelLine();
  933.  
  934. VAR
  935.   i,j: INTEGER;
  936.   y: INTEGER;
  937.   text: TextLine;
  938.  
  939. BEGIN
  940.   IF ~Scrollable THEN
  941.     g.SetAPen(rp,0); g.SetBPen(rp,0);
  942.     IF Fast THEN
  943.       g.ScrollRaster(rp,0,-fontHeight,0,0,NuScreen.width-1,NuScreen.height-1);
  944.       IF Sync THEN g.WaitTOF END;
  945.     ELSE
  946.       i := fontHeight;
  947.       REPEAT
  948.         g.ScrollRaster(rp,0,-1,0,0,NuScreen.width-1,NuScreen.height-1);
  949.         IF Sync THEN g.WaitTOF END;
  950.         DEC(i)
  951.       UNTIL i=0;
  952.     END;
  953.     IF TopLine.prev#NIL THEN Type(0,TopLine.prev) ELSE Type(0,FirstLine) END;
  954.   ELSE
  955.     IF ScreenPos=0 THEN
  956.       ri.ryOffset  := NumLines*fontHeight;
  957.       ScreenPos := NumLines;
  958.     END;
  959.     DEC(ScreenPos);
  960.     IF TopLine.prev#NIL THEN Type(ScreenPos,TopLine.prev) ELSE Type(ScreenPos,FirstLine) END;
  961.     y := (ScreenPos+1)*fontHeight;
  962.     IF Fast THEN
  963.       DEC(ri.ryOffset,fontHeight);
  964.       MakeThink(Sync,w,f);
  965.       DEC(y,fontHeight);
  966.       SYS.SETREG(0,g.BltBitMap(BM, 0,y, BM, 0,y+PageHeight, NuScreen.width,fontHeight , 0C0X, SHORTSET{0..7}, NIL));
  967.     ELSE
  968.       i := fontHeight;
  969.       REPEAT
  970.         DEC(ri.ryOffset);
  971.         MakeThink(Sync,f,f);
  972.         DEC(y);
  973.         SYS.SETREG(0,g.BltBitMap(BM, 0,y, BM, 0,y+PageHeight, NuScreen.width,1, 0C0X, SHORTSET{0..7}, NIL));
  974.         DEC(i);
  975.       UNTIL i=0;
  976.     END;
  977.   END;
  978. END DelLine;
  979.  
  980.  
  981. (*------  Convert Integer to String:  ------*)
  982.  
  983.  
  984. PROCEDURE IntToStr(VAR String: String;
  985.                        At,Chars: INTEGER;
  986.                        int: LONGINT);
  987.  
  988. VAR
  989.   Cnt: INTEGER;
  990.   Ziff: LONGINT;
  991.  
  992. BEGIN
  993.   INC(Chars,At);
  994.   IF (str.Length(String)<Chars) & (Chars < SIZE(String)) THEN
  995.     String[Chars] := 0X
  996.   END;
  997.   REPEAT
  998.     DEC(Chars);
  999.     String[Chars] := CHR(int MOD 10 + ORD(30X)); int := int DIV 10;
  1000.   UNTIL (Chars=At) OR (int=0);
  1001.   WHILE Chars>At DO DEC(Chars); String[Chars] := 20X END;
  1002. END IntToStr;
  1003.  
  1004.  
  1005. (*------  Convert String to Integer:  ------*)
  1006.  
  1007.  
  1008. PROCEDURE StrToInt(str: StringPtr; base: INTEGER): LONGINT;
  1009.  
  1010. VAR
  1011.   i,j: INTEGER;
  1012.   num: LONGINT;
  1013.   ch : CHAR;
  1014.   neg: BOOLEAN;
  1015.  
  1016. BEGIN
  1017.   num := 0; i := 0; neg := f;
  1018.   IF  str^[0] = '-'                   THEN str:=SYS.ADR(str[1]); neg := w END;
  1019.   IF  str^[0] = '$'                   THEN str:=SYS.ADR(str[1]); base:=16 END;
  1020.   IF (str^[0]='0')&(CAP(str^[1])='X') THEN str:=SYS.ADR(str[2]); base:=16 END;
  1021.   LOOP
  1022.     IF i=LEN(str^) THEN EXIT END;
  1023.     ch := CAP(str^[i]);
  1024.     IF ch=0X THEN EXIT END;
  1025.     j := ORD(ch);
  1026.     CASE ch OF
  1027.       "0".."9": DEC(j,ORD('0'))   |
  1028.       "A".."F": DEC(j,ORD('A')-10);
  1029.                 IF base=10 THEN base:=16; i:=-1; j:=0; num:=0 END;
  1030.       ELSE EXIT
  1031.     END;
  1032.     num := num * base + j;
  1033.     INC(i);
  1034.   END;
  1035.   IF neg THEN num := -num END;
  1036.   RETURN num
  1037. END StrToInt;
  1038.  
  1039.  
  1040. (*-------------------------------------------------------------------------*)
  1041.  
  1042.  
  1043. PROCEDURE GetStr(name: StringPtr; VAR str: String);
  1044. VAR i: INTEGER;
  1045. BEGIN
  1046.   i := -1;
  1047.   REPEAT
  1048.     INC(i); str[i] := name^[i]
  1049.   UNTIL (name^[i]=0X) OR (i=LEN(str)-1);
  1050.   str[i] := 0X
  1051. END GetStr;
  1052.  
  1053.  
  1054. (*-------------------------------------------------------------------------*)
  1055.  
  1056.  
  1057. PROCEDURE GetLength(t: TextLinePtr);
  1058.  
  1059. BEGIN
  1060.   TextLength := 0; AnzLines := 0;
  1061.   WHILE t#NIL DO INC(AnzLines); INC(TextLength,t.len); t := t.prev END;
  1062. END GetLength;
  1063.  
  1064.  
  1065. (*-------------------------------------------------------------------------*)
  1066.  
  1067.  
  1068. PROCEDURE NewDisplay();
  1069. (* Zeichnet ab BottomLine neu *)
  1070.  
  1071. VAR
  1072.   i: INTEGER;
  1073.   l: TextLinePtr;
  1074.  
  1075. BEGIN
  1076.   ClearBitMaps;
  1077.   l := BottomLine.prev;
  1078.   IF l#NIL THEN BottomLine := l END;
  1079.   l := BottomLine;
  1080.   i := NumLines-1;
  1081.   WHILE (i>0) & TryBottomnext() DO
  1082.     BottomLine := BottomLine.next;
  1083.     DEC(i);
  1084.   END;
  1085.   WHILE (i>0) & (l.prev#NIL) DO
  1086.     l := l.prev;
  1087.     DEC(i);
  1088.   END;
  1089.   TopLine := l.next;
  1090.   WHILE i<NumLines DO
  1091.     BottomLine := l;
  1092.     TypeTo(BottomLine^,i);
  1093.     INC(i);
  1094.     l := l.next;
  1095.   END;
  1096.   GetLength(BottomLine);
  1097.   Scroll := f;
  1098. END NewDisplay;
  1099.  
  1100.  
  1101. (*-------------------------------------------------------------------------*)
  1102.  
  1103.  
  1104. PROCEDURE * ShowProc;
  1105.  
  1106. VAR
  1107.   l: TextLinePtr;
  1108.   Down: BOOLEAN;               (* Scroll-Direction                  *)
  1109.   End: BOOLEAN;                (* Quit next time Space is pressed ? *)
  1110.   i,j,k,m: INTEGER;
  1111.   MyMsg: I.IntuiMessage;       (* contains Message                  *)
  1112.   Shift: BOOLEAN;              (* Shifted Keystroke ?               *)
  1113.   Alt: BOOLEAN;                (* Altered Keystroke ?               *)
  1114.   Find,FindStr: ARRAY 80 OF CHAR; (* findstring / capitalized findstring *)
  1115.   Goto: ARRAY 10 OF CHAR;      (* string containing goto line #  *)
  1116.   li: LONGINT;                 (* longint value of line to go to *)
  1117.   flen: INTEGER;               (* length of findstring *)
  1118.   HiText: TextLine;            (* Highlited textline *)
  1119.   OldHiText: TextLinePtr;      (* original, un-hilited text *)
  1120.   found: BOOLEAN;              (* TRUE, if find was successful *)
  1121.   chr: CHAR;                   (* converted keycode *)
  1122.  
  1123.  
  1124.   PROCEDURE WaitAllRead();
  1125.  
  1126.   BEGIN
  1127.     IF MyFile#NIL THEN
  1128.       Busy;
  1129.       SignalAllRead := w;
  1130.       SYS.SETREG(0,e.Wait(mySig));
  1131.       SignalAllRead := f;
  1132.       UnBusy;
  1133.     END;
  1134.   END WaitAllRead;
  1135.  
  1136.  
  1137.   PROCEDURE HiLite(at,len: INTEGER);
  1138.   (* Hilites len chars of BottomLine.text starting at position at *)
  1139.  
  1140.   VAR
  1141.     c: INTEGER;
  1142.     col: CHAR;
  1143.  
  1144.   BEGIN
  1145.     OldHiText := BottomLine; HiText := OldHiText^; BottomLine := SYS.ADR(HiText);
  1146.     IF at+len+2<MaxLen THEN
  1147.       c := 0; col := 5X;
  1148.       WHILE c<at DO
  1149.         IF HiText.text[c]<CHR(17) THEN col := HiText.text[c] END;
  1150.         INC(c);
  1151.       END;
  1152.       HiText.text[at] := CHR(17-ORD(col));
  1153.       c := at; INC(len,at);
  1154.       WHILE c<len DO
  1155.         HiText.text[c+1] := OldHiText.text[c];
  1156.         INC(c);
  1157.       END;
  1158.       HiText.text[c+1] := col;
  1159.       REPEAT
  1160.         HiText.text[c+2] := OldHiText.text[c];
  1161.         INC(c);
  1162.       UNTIL HiText.text[c-1]=0X;
  1163.     END;
  1164.     IF HiText.next#NIL THEN HiText.next.prev := SYS.ADR(HiText) END;
  1165.     IF HiText.prev#NIL THEN HiText.prev.next := SYS.ADR(HiText) END;
  1166.   END HiLite;
  1167.  
  1168.  
  1169.   PROCEDURE UnHiLite();
  1170.  
  1171.   BEGIN
  1172.     IF HiText.next#NIL THEN HiText.next.prev := OldHiText END;
  1173.     IF HiText.prev#NIL THEN HiText.prev.next := OldHiText END;
  1174.   END UnHiLite;
  1175.  
  1176.  
  1177.   PROCEDURE ChkBotNewDisp;
  1178.  
  1179.   VAR
  1180.     c: INTEGER;
  1181.     t: LONGINT;
  1182.  
  1183.   BEGIN
  1184.     IF ~ found THEN
  1185.       I.DisplayBeep(NIL);
  1186.       IF TopLine.prev=NIL THEN BottomLine := TopLine
  1187.                           ELSE BottomLine := TopLine.prev END;
  1188.     END;
  1189.     NewDisplay;
  1190.     IF found THEN UnHiLite END;
  1191.   END ChkBotNewDisp;
  1192.  
  1193.  
  1194.   PROCEDURE Search(): BOOLEAN;
  1195.   (* searches string and hilites it if found. result is TRUE if string found *)
  1196.  
  1197.   BEGIN
  1198.     i := 0;
  1199.     IF BottomLine.len<NumColumns THEN m := BottomLine.len ELSE m := NumColumns END;
  1200.     WHILE i<BottomLine.size DO
  1201.       j := 0; k := i;
  1202.       WHILE CAP(BottomLine.text[k])=FindStr[j] DO
  1203.         INC(j); INC(k);
  1204.         IF FindStr[j]=0X THEN
  1205.           SYS.SETREG(0,TryBottomnext());
  1206.           FindLine := BottomLine;
  1207.           HiLite(k-flen,flen);
  1208.           found := w; RETURN w;
  1209.         END;
  1210.       END;
  1211.       INC(i);
  1212.     END;
  1213.     RETURN f;
  1214.   END Search;
  1215.  
  1216.  
  1217.   PROCEDURE DisplayInfo(Fast: BOOLEAN);
  1218.   VAR IStr: String;
  1219.  
  1220.   BEGIN
  1221. (* File: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xx % (xxxxxx of xxxxxx Bytes) xxxxxx Lines *)
  1222.     IStr := "XFile: "; IStr[0] := 7X;
  1223.     IF onePlane THEN IStr[0] := 2X END;
  1224.     Append(IStr,SYS.ADR(OldName));
  1225.     Append(IStr,SYS.ADR("                              "));
  1226.     IStr[36] := 0X;
  1227.     Append(IStr,SYS.ADR("xxx % (xxxxxx of xxxxxx Bytes) xxxxxx Lines"));
  1228.     IntToStr(IStr,36,3,TextLength * 100 DIV FileLength);
  1229.     IntToStr(IStr,43,6,TextLength);
  1230.     IntToStr(IStr,53,6,FileLength);
  1231.     IntToStr(IStr,67,6,AnzLines-1);
  1232.     i := 79;
  1233.     REPEAT IStr[i] := 20X; INC(i) UNTIL (i>=255) OR (i>=NumColumns+2);
  1234.     IStr[i] := 0X;
  1235.     CopyToWriteText(SYS.ADR(IStr));
  1236.     AddBottomLine(SYS.ADR(writeText),Fast);
  1237.     Info := w;
  1238.   END DisplayInfo;
  1239.  
  1240.   PROCEDURE GetString(VAR str: ARRAY OF CHAR; int: BOOLEAN);
  1241.   VAR
  1242.     msg: I.IntuiMessagePtr;
  1243.     class: LONGSET;
  1244.     oldheight: INTEGER;
  1245.  
  1246.   BEGIN
  1247.     MakeThink(f,f,w);
  1248.     Busy;
  1249.     NuWindow.leftEdge    := 100;
  1250.     NuWindow.topEdge     := NuScreen.height DIV 2 - 6;
  1251.     IF Scrollable THEN INC(NuWindow.topEdge,ri.ryOffset) END;
  1252.     NuWindow.width       := NuScreen.width-200;
  1253.     NuWindow.height      := Screen.font.ySize+4;
  1254.     NuWindow.blockPen    := 1;
  1255.     NuWindow.idcmpFlags  := LONGSET{I.gadgetUp,I.activeWindow,I.inactiveWindow};
  1256.     NuWindow.flags       := LONGSET{I.rmbTrap,I.activate};
  1257.     NuWindow.firstGadget := SYS.ADR(StrGadget);
  1258.     NuWindow.screen      := Screen;
  1259.     NuWindow.type        := I.customScreen;
  1260.     StrGadget.leftEdge   := 4;
  1261.     StrGadget.topEdge    := 2;
  1262.     StrGadget.width      := NuWindow.width-8;
  1263.     StrGadget.height     := NuWindow.height-4;
  1264.     StrGadget.activation := {I.stringCenter,I.relVerify};
  1265.     IF int THEN INCL(StrGadget.activation,I.longint) END;
  1266.     StrGadget.gadgetType := I.strGadget;
  1267.     StrGadget.specialInfo:= SYS.ADR(StrInfo);
  1268.     StrInfo.buffer       := SYS.ADR(str);
  1269.     StrInfo.maxChars     := SHORT(LEN(str))-1;
  1270.     oldheight := Screen.height;
  1271.     IF Scrollable THEN INC(Screen.height,Screen.height) END;
  1272.     win := I.OpenWindow(NuWindow);
  1273.     Screen.height := oldheight;
  1274.     IF win#NIL THEN
  1275.       e.WaitPort(win.userPort);
  1276.       SYS.SETREG(0,I.ActivateGadget(StrGadget,win,NIL));
  1277.       LOOP
  1278.         e.WaitPort(win.userPort);
  1279.         msg := e.GetMsg(win.userPort);
  1280.         IF msg#NIL THEN
  1281.           class := msg.class;
  1282.           e.ReplyMsg(msg);
  1283.           IF I.gadgetUp IN class THEN
  1284.             EXIT
  1285.           ELSIF I.inactiveWindow IN class THEN
  1286.             I.OldActivateWindow(win);
  1287.             g.WaitTOF; g.WaitTOF; g.WaitTOF;
  1288.             SYS.SETREG(0,I.ActivateGadget(StrGadget,win,NIL));
  1289.           END;
  1290.         END;
  1291.       END;
  1292.       I.CloseWindow(win); win := NIL;
  1293.     END;
  1294.     UnBusy;
  1295.   END GetString;
  1296.  
  1297.  
  1298.   PROCEDURE Help; (* executed when HELP or H is pressed *)
  1299.   TYPE
  1300.     UsageType = ARRAY 26 OF StringPtr;
  1301.   CONST
  1302.     Usage = UsageType(SYS.ADR(""),
  1303.                       SYS.ADR("\x13                \x15  MuchMore V3.2.7 Commands:  "),
  1304.                       SYS.ADR(""),
  1305.                       SYS.ADR(" \x0dSpace\x05,\x0d LMB\x05:         Start / Stop scrolling. Quit at end of file."),
  1306.                       SYS.ADR(" \x0dBackSpace\x05,\x0d RMB\x05:     Start / Stop scrolling backwards."),
  1307.                       SYS.ADR(" \x0dUp\x05/\x0dDown\x05:            Move one line \x0dup\x05 or \x0ddown\x05."),
  1308.                       SYS.ADR(" \x0dShift \x05+\x0d Up\x05/\x0dDn\x05:      Start / Stop quick scrolling \x0dup\x05 or \x0ddown\x05."),
  1309.                       SYS.ADR(" \x0dControl\x05:            Increase scroll speed"),
  1310.                       SYS.ADR(" \x0dAlt\x05+\x0dUp\x05/\x0dDn\x05,\x0d PgUp\x05/\x0dDn\x05: Move one page \x0dup\x05 or \x0ddown\x05."),
  1311.                       SYS.ADR(" \x0dT\x05,\x0d Home \x05/\x0d B\x05,\x0d End\x05:   Goto \x0dt\x05op / \x0db\x05ottom of text."),
  1312.                       SYS.ADR(" \x0dF\x05,\x0dN\x05,\x0dP\x05:              \x0dF\x05ind string, \x0dN\x05ext, \x0dP\x05revious occurance"),
  1313.                       SYS.ADR(" \x0dShift \x05+\x0d Fn\x05:         Set textmarker #n to current position"),
  1314.                       SYS.ADR(" \x0dFn\x05:                 Goto marker #n or set marker #n if it wasn't set yet"),
  1315.                       SYS.ADR(" \x0dG\x05:                  \x0dG\x05oto line #n"),
  1316.                       SYS.ADR(" \x0dNK 0\x05:               Display Filelength etc."),
  1317.                       SYS.ADR(" \x0dShift \x05+\x0d Alt \x05+\x0d O\x05:    Create print\x0do\x05ut of the text"),
  1318.                       SYS.ADR(" \x0dW\x05:                  \x0dW\x05rite block between Marker #1 and #2 to file or prt"),
  1319.                       SYS.ADR(" \x0dL\x05:                  \x0dL\x05oad new text"),
  1320.                       SYS.ADR(" \x0dHELP\x05,\x0d H\x05:            Show Commands."),
  1321.                       SYS.ADR(" \x0dESC\x05,\x0d Q\x05,\x0d X\x05,\x0d NK 5\x05:\x0d    Q\x05uit."),
  1322.                       SYS.ADR(""),
  1323.                       SYS.ADR("© \x131992 Fridtjof Siebert, Nobileweg 67, D-7000 Stuttgart 40"),
  1324.                       SYS.ADR("  \x131993 Christian Stiens, Heustiege 2, D-4710 Lüdinghausen"),
  1325.                       SYS.ADR("  \x13Please refer to MuchMore.ReadMe for a detailed copyright notice"),
  1326.                       SYS.ADR(""),
  1327.                       SYS.ADR("  This is another product of the Amiga MODULA & OBERON Klub Stuttgart - \x0d\x13AMOK"));
  1328.   VAR
  1329.     i,j: INTEGER;
  1330.  
  1331.   BEGIN
  1332.     ClearBitMaps();
  1333.     j := (NumLines - 26) DIV 2; IF j<0 THEN j:=0 END;
  1334.     i := 0;
  1335.     WHILE (i<26) & (i+j<NumLines) DO
  1336.       WriteTo(Usage[i],j+i);
  1337.       INC(i);
  1338.     END;
  1339.     LOOP
  1340.       e.WaitPort(Window.userPort);
  1341.       MyMsgPtr := e.GetMsg(Window.userPort);
  1342.       IF (LONGSET{I.rawKey,I.mouseButtons}*MyMsgPtr.class#LONGSET{}) & (MyMsgPtr.code<128) THEN EXIT END;
  1343.       e.ReplyMsg(MyMsgPtr);
  1344.     END;
  1345.     e.ReplyMsg(MyMsgPtr);
  1346.     BottomLine := TopLine;
  1347.     NewDisplay
  1348.   END Help;
  1349.  
  1350.  
  1351.   PROCEDURE Bottom;  (* executed when END or B is pressed *)
  1352.  
  1353.   BEGIN
  1354.     WaitAllRead;
  1355.     BottomLine := LastLine;
  1356.     NewDisplay
  1357.   END Bottom;
  1358.  
  1359.  
  1360.   PROCEDURE Space(): BOOLEAN;  (* executed if space or LMB is pressed *)
  1361.   (* IF result=w THEN EXIT END *)
  1362.   VAR oldFast: BOOLEAN;
  1363.  
  1364.   BEGIN
  1365.     oldFast := Fast;
  1366.     Fast := Shift;
  1367.     IF (MyFile=NIL) & (BottomLine.next=NIL) THEN
  1368.       IF End THEN RETURN w ELSE End:=w END;
  1369.     ELSE
  1370.       End := f;
  1371.     END;
  1372.     IF Down THEN
  1373.       IF Scroll OR End THEN DisplayInfo(oldFast) END;
  1374.       Scroll := ~Scroll;
  1375.     ELSE
  1376.       Down := w;
  1377.       Scroll := w;
  1378.     END;
  1379.     RETURN f;
  1380.   END Space;
  1381.  
  1382.  
  1383.   PROCEDURE BackSpace;  (* executed if backspace or RMB is pressed *)
  1384.  
  1385.   BEGIN
  1386.     Fast := Shift;
  1387.     Scroll := Down OR ~ Scroll;
  1388.     Down := f
  1389.   END BackSpace;
  1390.  
  1391.  
  1392. BEGIN
  1393.   (* $IF SmallData *)
  1394.   SYS.SETREG(13,e.exec.thisTask.userData);
  1395.   (* $END *)
  1396.   SYS.SETREG(0,e.Wait(mySig));
  1397.  
  1398.   Down := w; End := f; Find[0] := 0X; Goto[0] := 0X;
  1399.  
  1400.   LOOP
  1401.  
  1402.     IF NewDisp THEN NewDisp := f; NewDisplay END;
  1403.  
  1404. (*------  Type Text:  ------*)
  1405.  
  1406.     LOOP
  1407.       IF Scroll THEN
  1408.         IF Down THEN
  1409.           ScrollDown(Fast);
  1410.           Scroll := (MyFile#NIL) OR (BottomLine.next#NIL);
  1411.         ELSE
  1412.           ScrollUp(Fast);
  1413.           Scroll := (TopLine.prev#NIL) & (TopLine.prev.prev#NIL);
  1414.         END;
  1415.       ELSE
  1416.         MakeThink(f,f,w);
  1417.         e.WaitPort(Window.userPort);
  1418.       END;
  1419.  
  1420.       MyMsgPtr := e.GetMsg(Window.userPort);
  1421.  
  1422.       IF (MyMsgPtr#NIL) THEN
  1423.         IF ~(I.inactiveWindow IN MyMsgPtr.class) THEN EXIT END;
  1424.         e.ReplyMsg(MyMsgPtr);
  1425.         I.OldModifyIDCMP(Window,MyIdcmp-LONGSET{I.mouseButtons});
  1426.         e.WaitPort(Window.userPort);
  1427.         I.OldModifyIDCMP(Window,MyIdcmp);
  1428.       END;
  1429.     END;
  1430.  
  1431.     MyMsg := MyMsgPtr^;
  1432.     e.ReplyMsg(MyMsgPtr);
  1433.  
  1434.     IF (I.rawKey       IN MyMsg.class) & (MyMsg.code<80H) OR
  1435.        (I.mouseButtons IN MyMsg.class) & ({ie.leftButton,ie.rightButton}*MyMsg.qualifier#{})
  1436.     THEN
  1437.       IF ~Info THEN
  1438.         IF MyMsg.code=0FH THEN DisplayInfo(Fast); Scroll := f END;
  1439.       ELSE
  1440.         DelLine;
  1441.         Info := f
  1442.       END;
  1443.     END;
  1444.  
  1445.     Shift := {} # {ie.lShift,ie.rShift,ie.capsLock} * MyMsg.qualifier;
  1446.     Alt   := {} # {ie.lAlt  ,ie.rAlt}               * MyMsg.qualifier;
  1447.     Sync  := ~  (                     ie.control IN MyMsg.qualifier);
  1448.     IF ~(Sync OR Alt) THEN Shift := w END;
  1449.  
  1450.     IF I.mouseButtons IN MyMsg.class THEN
  1451.  
  1452.       IF    (ie.leftButton IN MyMsg.qualifier) & Space() THEN EXIT
  1453.       ELSIF ie.rightButton IN MyMsg.qualifier            THEN BackSpace END;
  1454.  
  1455.     ELSIF (I.rawKey IN MyMsg.class) & (MyMsg.code<80H) THEN
  1456.  
  1457.       CASE MyMsg.code OF
  1458.  
  1459.       | 40H: IF Space() THEN EXIT END                 (* Space *)
  1460.  
  1461.       | 41H: BackSpace                                (* BackSpace *)
  1462.  
  1463.       | 4DH,1EH,1FH:                                  (* Down *)
  1464.             IF Shift THEN
  1465.               Scroll := ~(Down & Scroll) OR ~ Fast;
  1466.               Fast := w; Down := w;
  1467.             ELSE
  1468.               IF Alt OR (MyMsg.code=1FH) THEN
  1469.                 IF BottomLine.next#NIL THEN BottomLine := BottomLine.next END;
  1470.                 NewDisplay;
  1471.               ELSE
  1472.                 ScrollDown(~ Shift);
  1473.               END;
  1474.               Scroll := f;
  1475.             END
  1476.  
  1477.       | 4CH,3EH,3FH:                                      (* Up *)
  1478.             IF Shift THEN
  1479.               Scroll := Down OR ~ Scroll OR ~ Fast;
  1480.               Fast := w; Down := f;
  1481.             ELSE
  1482.               IF Alt OR (MyMsg.code=3FH) THEN
  1483.                 IF TopLine.prev#NIL THEN
  1484.                   i := NumLines-1;
  1485.                   BottomLine := TopLine;
  1486.                   WHILE (i>0) & (BottomLine.prev#NIL) DO
  1487.                     BottomLine := BottomLine.prev;
  1488.                     DEC(i);
  1489.                   END;
  1490.                   NewDisplay;
  1491.                 END;
  1492.               ELSE
  1493.                 ScrollUp(~ Shift);
  1494.               END;
  1495.               Scroll := f;
  1496.             END;
  1497.  
  1498.       | 44H,43H:                                          (* CR *)
  1499.             ScrollDown(f);
  1500.             Scroll := f;
  1501.  
  1502.       | 3DH: BottomLine := FirstLine; NewDisplay          (* Home *)
  1503.  
  1504.       | 1DH: Bottom                                       (* End *)
  1505.  
  1506.       | 50H..59H:                                         (* F1..F10 *)
  1507.             i := MyMsg.code-50H;
  1508.             IF ~ Shift & (TextMarkers[i]#NIL) THEN
  1509.               BottomLine := TextMarkers[i];
  1510.               IF BottomLine.prev#NIL THEN BottomLine := BottomLine.prev END;
  1511.               NewDisplay;
  1512.             ELSE
  1513.               TextMarkers[i] := TopLine;
  1514.             END
  1515.  
  1516.       | 5FH:  Help
  1517.  
  1518.       | 45H,2EH: IF ~ Alt THEN EXIT END                   (* Quit *)
  1519.  
  1520.       ELSE
  1521.  
  1522.         IF MyMsg.code<40H THEN (* examine vanilla keycode: *)
  1523.  
  1524.           chr := KeyMap[MyMsg.code];
  1525.  
  1526.           CASE chr OF
  1527.  
  1528.           | "t": BottomLine := FirstLine; NewDisplay      (* Home *)
  1529.  
  1530.           | "b": Bottom;                                  (* End *)
  1531.  
  1532.           | "f","n","p":                                  (* Find, Next, Previous *)
  1533.  
  1534.             IF chr="f" THEN
  1535.               GetString(Find,f); FindLine := NIL; flen := 0;
  1536.               LOOP
  1537.                 FindStr[flen] := CAP(Find[flen]);
  1538.                 IF    FindStr[flen]>80X THEN DEC(FindStr[flen],32)
  1539.                 ELSIF FindStr[flen]=0X  THEN EXIT END;
  1540.                 INC(flen);
  1541.               END;
  1542.               ClearBitMaps();
  1543.             END;
  1544.             found := f;
  1545.             IF FindStr[0]#0X THEN
  1546.               Busy;
  1547.               i := NumLines;
  1548.               IF FindLine#NIL THEN FindLine := FindLine.next END;
  1549.               WHILE (i>0) & (BottomLine#NIL) & (BottomLine#FindLine) DO
  1550.                 BottomLine := BottomLine^.prev; DEC(i);
  1551.               END;
  1552.               IF (BottomLine#FindLine) OR (BottomLine=NIL) THEN BottomLine := TopLine END;
  1553.               IF chr#"p" THEN (* next *)
  1554.                 WHILE (BottomLine#NIL) & ~ Search() DO
  1555.                   SYS.SETREG(0,TryBottomnext());
  1556.                   BottomLine := BottomLine.next;
  1557.                 END;
  1558.               ELSE                   (* previous *)
  1559.                 IF BottomLine.prev#NIL THEN BottomLine:=BottomLine.prev END;
  1560.                 REPEAT
  1561.                   BottomLine := BottomLine.prev
  1562.                 UNTIL (BottomLine=NIL) OR Search();
  1563.               END;
  1564.               IF BottomLine#NIL THEN
  1565.                 li := NumLines DIV 2;
  1566.                 WHILE (li>0) & (BottomLine.prev#NIL) DO BottomLine := BottomLine.prev; DEC(li) END;
  1567.               END;
  1568.               UnBusy;
  1569.             ELSE
  1570.               BottomLine := NIL
  1571.             END;
  1572.             ChkBotNewDisp;
  1573.  
  1574.           | "w":                                                (* write block *)
  1575.  
  1576.             IF (TextMarkers[0]#NIL) & (TextMarkers[1]#NIL) & ~ print & ~ save THEN
  1577.               savefrom := 0; savesize := 0;
  1578.               l := TextMarkers[0].prev; WHILE l.prev#NIL DO l := l.prev; INC(savefrom,l.len) END;
  1579.               l := TextMarkers[1].prev; WHILE l#NIL DO INC(savesize,l.len); l := l.prev END;
  1580.               l := TextMarkers[1]; i := NumLines; WHILE (i>1) & (l#NIL) DO DEC(i); INC(savesize,LONG(l.len)); l := l.next END;
  1581.               DEC(savesize,savefrom);
  1582.               IF savesize>0 THEN
  1583.                 GetString(WriteName,f);
  1584.                 WaitAllRead; save := w; e.Signal(SYS.ADR(Me.task),mySig); NewDisplay;
  1585.               END
  1586.             END
  1587.  
  1588.           | "o": IF Shift & Alt & ~print & ~save THEN           (* Printout *)
  1589.                  PStr := 'TYPE "'; Append(PStr,SYS.ADR(Name)); Append(PStr,SYS.ADR('" TO PRT:'));
  1590.                  WaitAllRead; print := w; e.Signal(SYS.ADR(Me.task),mySig);
  1591.                END
  1592.  
  1593.           | "l": ClearBitMaps;                                  (* Load Text *)
  1594.                NewText := w; e.Signal(SYS.ADR(Me.task),mySig);
  1595.                REPEAT UNTIL (mySigBit IN e.Wait(mySig)) & ~ NewText |
  1596.  
  1597.           | "g":                                                (* goto *)
  1598.             GetString(Goto,w);
  1599.             li := SHORT(StrInfo.longInt);
  1600.             Busy;
  1601.             BottomLine := FirstLine;
  1602.             WHILE (li>0) & TryBottomnext() DO
  1603.               BottomLine := BottomLine.next;
  1604.               DEC(li)
  1605.             END;
  1606.             UnBusy;
  1607.             NewDisplay
  1608.  
  1609.           | "h": Help                                           (* Help *)
  1610.  
  1611.           | "q","x": EXIT                                       (* Quit *)
  1612.  
  1613.           ELSE END;
  1614.  
  1615.         END;   (* IF MyMsg.code<40H THEN *)
  1616.  
  1617.       END;   (* CASE MyMsg.code OF *)
  1618.  
  1619.     END;   (* IF I.rawKey IN MyMsg.class THEN *)
  1620.  
  1621.   END;   (* LOOP *)
  1622.  
  1623.   Done := w;
  1624.   e.Signal(SYS.ADR(Me.task),mySig);
  1625.   LOOP SYS.SETREG(0,e.Wait(LONGSET{})) END;
  1626.  
  1627. END ShowProc;
  1628.  
  1629. (* $Debug= *)
  1630.  
  1631. (*--------------------------  File Requester:  ----------------------------*)
  1632.  
  1633.  
  1634. PROCEDURE FileReq(VAR Name: String);
  1635.  
  1636. CONST
  1637.   dummy     = u.user + 80000H;
  1638.   taghail   = dummy + 1;
  1639.   window    = dummy + 2;
  1640.   leftEdge  = dummy + 3;         (* Initialize LeftEdge                  *)
  1641.   topEdge   = dummy + 4;         (* Initialize TopEdge                   *)
  1642.   width     = dummy + 5;
  1643.   height    = dummy + 6;
  1644.   hookFunc  = dummy + 7;         (* Hook function pointer                *)
  1645.   file      = dummy + 8;         (* Initial name of file follows         *)
  1646.   dir       = dummy + 9;         (* Initial string for filerequest dir   *)
  1647.   pattern   = dummy + 10;
  1648.   funcFlags = dummy + 20;
  1649.   fiDir     = u.user + 50;
  1650.   longPath  = 0;
  1651.   patGad    = 0;
  1652.  
  1653. VAR
  1654.   fr: FileRequesterPtr;
  1655.   pscr: I.ScreenPtr;
  1656.   res: BOOLEAN;
  1657.  
  1658.   PROCEDURE AllocAslRequest  {asl,-48} (type{0}: LONGINT;
  1659.                                         tag{8}..: e.APTR): FileRequesterPtr;
  1660.   PROCEDURE FreeAslRequest   {asl,-54} (fr{8}: FileRequesterPtr);
  1661.   PROCEDURE RequestFile      {asl,-42} (fr{8}: FileRequesterPtr): e.APTR;
  1662.  
  1663.   PROCEDURE FileRequest{arp,-294}(VAR filereq{8}: FileRequester): BOOLEAN;
  1664.  
  1665. BEGIN
  1666.   LOOP
  1667.     j := SHORT(str.Length(Name));
  1668.     WHILE (j>0) & (Name[j]#":") & (Name[j]#"/") DO DEC(j) END;
  1669.     IF j=0 THEN j := -1 END;
  1670.     i := 0;
  1671.     WHILE i<=j DO Dirname[i] := Name[i]; INC(i) END; Dirname[i] := 0X;
  1672.     j := 0;
  1673.     REPEAT Filename[j] := Name[i]; INC(j); INC(i) UNTIL Name[i-1]=0X;
  1674.  
  1675.     LOOP
  1676.       IF I.int.libNode.version >= 37 THEN
  1677.         pscr := I.LockPubScreen(NIL);
  1678.         IF pscr#NIL THEN
  1679.           I.ScreenToFront(pscr);
  1680.           I.UnlockPubScreen(NIL,pscr);
  1681.           EXIT
  1682.         END;
  1683.       END;
  1684.       SYS.SETREG(0,I.WBenchToFront());
  1685.       EXIT
  1686.     END;
  1687.  
  1688.     IF asl=NIL THEN asl := e.OpenLibrary("asl.library",36) END;
  1689.     IF asl#NIL THEN
  1690.       fr := AllocAslRequest(0,taghail, SYS.ADR(MuchText),
  1691.                               leftEdge,25,
  1692.                               topEdge, 15,
  1693.                               width,   300,
  1694.                               height,  184,
  1695.                               file,    SYS.ADR(Filename),
  1696.                               dir,     SYS.ADR(Dirname),
  1697.                               pattern, SYS.ADR(Pattern),
  1698.                               funcFlags,ASH(1,patGad),
  1699.                               u.done);
  1700.       IF fr=NIL THEN Request(oom) END;
  1701.       res := RequestFile(fr)#NIL;
  1702.       IF res THEN
  1703.         Filename := fr.ddef^;
  1704.         Dirname  := fr.ddir^;
  1705.       END;
  1706.       FreeAslRequest(fr);
  1707.       IF ~res THEN EXIT END;
  1708.     ELSE
  1709.       IF arp=NIL THEN arp := e.OpenLibrary("arp.library",39) END;
  1710.       IF arp#NIL THEN
  1711.         FR.hail := SYS.ADR(MuchText);
  1712.         FR.ddef := SYS.ADR(Filename);
  1713.         FR.ddir := SYS.ADR(Dirname);
  1714.         FR.flags2 := SHORTSET{longPath};
  1715.         FR.wind := NIL;
  1716.         IF ~FileRequest(FR) THEN EXIT END;
  1717.       ELSE
  1718.         Request(noarp)
  1719.       END;
  1720.     END;
  1721.     Name := Dirname;
  1722.     i := SHORT(str.Length(Name));
  1723.     IF (i>0) THEN
  1724.       CASE Name[i-1] OF "/",":": ELSE
  1725.         Name[i] := "/"; INC(i);
  1726.       END;
  1727.     END;
  1728.     j := 0;
  1729.     LOOP
  1730.       Name[i] := Filename[j];
  1731.       IF (Name[i]=0X) OR (i=255) THEN EXIT END;
  1732.       INC(i);
  1733.       INC(j);
  1734.     END;
  1735.     Name[i] := 0X;
  1736.     IF Screen#NIL THEN I.ScreenToFront(Screen) END;
  1737.     IF Window#NIL THEN IF I.ActivateWindow(Window) THEN END END;
  1738.     RETURN
  1739.   END;
  1740.   HALT(0);
  1741. END FileReq;
  1742.  
  1743.  
  1744. (*--------------------------  Decrunch:  ----------------------------*)
  1745.  
  1746.  
  1747. PROCEDURE DirExists(name: ARRAY OF CHAR): BOOLEAN; (* $CopyArrays- *)
  1748. VAR lock: d.FileLockPtr;
  1749.     result: BOOLEAN;
  1750.     oldwp: e.APTR;
  1751. BEGIN
  1752.   result := f;
  1753.   oldwp := Me.windowPtr;
  1754.   Me.windowPtr := -1;
  1755.   lock := d.Lock(name,d.sharedLock);
  1756.   IF lock # NIL THEN
  1757.     result := w;
  1758.     d.UnLock(lock)
  1759.   END;
  1760.   Me.windowPtr := oldwp;
  1761.   RETURN result
  1762. END DirExists;
  1763.  
  1764.  
  1765. PROCEDURE RFProc; (* $EntryExitCode- *)
  1766. BEGIN
  1767.   SYS.INLINE(016C0U, 04E75U)
  1768. END RFProc;
  1769.  
  1770.  
  1771. PROCEDURE Decrunch;
  1772.  
  1773. CONST
  1774.   tagBase    = u.user + ORD("X")*256 + ORD("P");
  1775.   inName     = tagBase+01H;
  1776.   inFH       = tagBase+02H;
  1777.   outName    = tagBase+10H;
  1778.   password   = tagBase+24H;
  1779.   getError   = tagBase+25H;
  1780.   shortError = tagBase+31H;
  1781.   typePacked = 1;
  1782.  
  1783. TYPE
  1784.   XpkFib = STRUCT
  1785.     type       : LONGINT;    (* Unpacked, packed, archive? *)
  1786.     uLen       : LONGINT;
  1787.     cLen       : LONGINT;
  1788.     nLen       : LONGINT;
  1789.     uCur       : LONGINT;
  1790.     cCur       : LONGINT;
  1791.     id         : LONGINT;
  1792.     packer     : ARRAY 6 OF CHAR;
  1793.     subVersion : INTEGER;
  1794.     masVersion : INTEGER;
  1795.     flags      : LONGSET;
  1796.     head       : ARRAY 16 OF CHAR;
  1797.     ratio      : LONGINT;
  1798.     reserved   : ARRAY 8 OF LONGINT;
  1799.   END;
  1800.  
  1801. VAR
  1802.   file: d.FileHandlePtr;
  1803.   err: LONGINT;
  1804.   xpkFib: XpkFib;
  1805.   errBuf: ARRAY 81 OF CHAR;
  1806.  
  1807.   PROCEDURE ExamineTags {xpk,-36}(VAR fib{8}  : XpkFib;
  1808.                                   tag1{9}..   : e.APTR): LONGINT;
  1809.   PROCEDURE UnpackTags  {xpk,-48}(tag1{8}..   : e.APTR): LONGINT;
  1810.  
  1811. BEGIN
  1812.   Decrunched := f;
  1813.   OldName := Name;
  1814.  
  1815.   IF DirExists("T:") THEN Name := "T:" ELSE Name := "RAM:" END;
  1816.  
  1817.   e.RawDoFmt("MM_decr.%lx",SYS.ADR(Me),RFProc,SYS.ADR(Name[str.Length(Name)]));
  1818.  
  1819.   IF xpk=NIL THEN
  1820.     xpk := e.OpenLibrary("xpkmaster.library",1);
  1821.   END;
  1822.   IF xpk#NIL THEN
  1823.     err := ExamineTags(xpkFib,inFH,SYS.VAL(LONGINT,MyFile),u.done);
  1824.     IF (err#0) & (err#-20) THEN
  1825.       Request(oom)
  1826.     END;
  1827.     IF (err=-20) OR (xpkFib.type#typePacked) THEN
  1828.       Name := OldName;
  1829.       RETURN
  1830.     END;
  1831.     Busy;
  1832.     err := UnpackTags(inFH,   SYS.VAL(LONGINT,MyFile),
  1833.                   outName,    SYS.ADR(Name),
  1834.                   password,   SYS.ADR(Password),
  1835.                   getError,   SYS.ADR(errBuf),
  1836.                   shortError, e.true,
  1837.                   u.done);
  1838.     UnBusy;
  1839.     IF err#0 THEN Request(errBuf) END;
  1840.     file := d.Open(Name,d.oldFile);
  1841.     IF file#NIL THEN
  1842.       Decrunched := w;
  1843.       d.OldClose(MyFile);
  1844.       MyFile := file;
  1845.       RETURN
  1846.     ELSE
  1847.       Request(cof);
  1848.     END;
  1849.   END;
  1850.   Name := OldName;
  1851. END Decrunch;
  1852.  
  1853.  
  1854. (*-----------------  Screen Mode Requester:  ------------------------*)
  1855.  
  1856.  
  1857. PROCEDURE GetNode (VAR list: e.List; index: LONGINT): e.NodePtr;
  1858.   VAR n: e.NodePtr;
  1859. BEGIN
  1860.   n := list.head;
  1861.   WHILE index > 0 DO
  1862.     IF n.succ=NIL THEN RETURN NIL END;
  1863.     n := n.succ;
  1864.     DEC(index);
  1865.   END;
  1866.   RETURN n;
  1867. END GetNode;
  1868.  
  1869.  
  1870. PROCEDURE ScreenModeReq (VAR displayID : LONGINT): INTEGER;
  1871. CONST
  1872.   gadLISTVIEW    = 1;
  1873.   gadBUTTONSave  = 2;
  1874.   gadBUTTONUse   = 3;
  1875.   gadBUTTONCancel= 4;
  1876.  
  1877.   Topaz80 = g.TextAttr(SYS.ADR("topaz.font"), 8, SHORTSET{}, SHORTSET{});
  1878.  
  1879. TYPE
  1880.   MyNodePtr = UNTRACED POINTER TO MyNode;
  1881.   MyNode = STRUCT (node: e.Node)
  1882.              displayID: LONGINT;
  1883.            END;
  1884.  
  1885. VAR
  1886.   ng          : gt.NewGadget;
  1887.   gad,glist   : I.GadgetPtr;
  1888.   win         : I.WindowPtr;
  1889.   pub         : I.ScreenPtr;
  1890.   result,index: INTEGER;
  1891.   firstindex  : INTEGER;
  1892.   topborder   : INTEGER;
  1893.   terminated  : BOOLEAN;
  1894.   lvlist      : e.List;
  1895.   lvSelectedTag:LONGINT;
  1896.   vi          : e.APTR;
  1897.   imsg        : I.IntuiMessagePtr;
  1898.   node        : MyNodePtr;
  1899.   dispID      : LONGINT;
  1900.   displayInfo : g.DisplayInfo;
  1901.   nameInfo    : g.NameInfo;
  1902. BEGIN
  1903.   (* $IFNOT ClearVars *)
  1904.   win := NIL; vi := NIL; glist := NIL; pub := NIL; result := 0;
  1905.   (* $END *)
  1906.  
  1907.   LOOP
  1908.     pub := I.LockPubScreen(NIL);         IF pub=NIL THEN EXIT END;
  1909.     vi  := gt.GetVisualInfo(pub,u.done); IF vi =NIL THEN EXIT END;
  1910.   
  1911.     topborder := pub.wBorTop + pub.font.ySize + 1;
  1912.  
  1913.     gad := gt.CreateContext(glist);
  1914.  
  1915.     ng.textAttr := SYS.ADR(Topaz80);
  1916.     ng.visualInfo := vi;
  1917.     ng.userData := NIL;
  1918.  
  1919.     ng.leftEdge := 16+100*0;
  1920.     ng.topEdge := 90+topborder;
  1921.     ng.width := 64;
  1922.     ng.height := 12;
  1923.     ng.gadgetText := SYS.ADR("Save");
  1924.     ng.gadgetID := gadBUTTONSave;
  1925.     ng.flags := LONGSET{};
  1926.  
  1927.     gad := gt.CreateGadget(gt.buttonKind, gad, ng, u.done);
  1928.  
  1929.     ng.leftEdge := 16+100*1;
  1930.     ng.gadgetText := SYS.ADR("Use");
  1931.     ng.gadgetID := gadBUTTONUse;
  1932.  
  1933.     gad := gt.CreateGadget(gt.buttonKind, gad, ng, u.done);
  1934.  
  1935.     ng.leftEdge := 16+100*2;
  1936.     ng.gadgetText := SYS.ADR("Cancel");
  1937.     ng.gadgetID := gadBUTTONCancel;
  1938.  
  1939.     gad := gt.CreateGadget(gt.buttonKind, gad, ng, u.done);
  1940.  
  1941.     lvlist.head := SYS.ADR(lvlist.tail);
  1942.     lvlist.tail := NIL;
  1943.     lvlist.tailPred := SYS.ADR(lvlist.head);
  1944.  
  1945.     index := 0;
  1946.     firstindex := -1;
  1947.     dispID := g.NextDisplayInfo(g.invalidID);
  1948.  
  1949.     WHILE dispID # g.invalidID DO
  1950.       IF (g.GetDisplayInfoData(NIL,displayInfo,SIZE(displayInfo),g.dtagDisp,dispID) > 0) &
  1951.          (displayInfo.notAvailable = 0) &
  1952.          (LONGSET{g.isHAM,g.isExtraHalfBrite,g.isDualPF} * displayInfo.propertyFlags = LONGSET{}) &
  1953.          (g.GetDisplayInfoData(NIL,nameInfo,SIZE(nameInfo),g.dtagName,dispID) > 0)
  1954.       THEN
  1955.         SYS.ALLOCATE(node);
  1956.         IF node # NIL THEN
  1957.           SYS.ALLOCATE(node.node.name);
  1958.           IF node.node.name # NIL THEN
  1959.             COPY(nameInfo.name,node.node.name^);
  1960.             node.displayID := dispID;
  1961.             e.AddTail(lvlist, node);
  1962.             IF dispID=displayID THEN firstindex := index END;
  1963.             INC(index);
  1964.           ELSE
  1965.             EXIT
  1966.           END;
  1967.         ELSE
  1968.           EXIT
  1969.         END;
  1970.       END;
  1971.       dispID := g.NextDisplayInfo(dispID);
  1972.     END;
  1973.  
  1974.     ng.leftEdge := 16;
  1975.     ng.topEdge := 16+topborder;
  1976.     ng.width := 265;
  1977.     ng.height := 66;
  1978.     ng.gadgetText := SYS.ADR("Choose Display Mode:");
  1979.     ng.gadgetID := gadLISTVIEW;
  1980.     ng.flags := LONGSET{gt.highLabel,gt.placeTextAbove};
  1981.  
  1982.     IF firstindex >= 0 THEN lvSelectedTag := gt.lvSelected
  1983.                        ELSE lvSelectedTag := u.ignore END;
  1984.  
  1985.     gad := gt.CreateGadget(gt.listViewKind, gad, ng,
  1986.                     gt.lvLabels,       SYS.ADR(lvlist),
  1987.                     gt.lvShowSelected, NIL,
  1988.                     I.layoutaSpacing,  2,
  1989.                     lvSelectedTag,     firstindex,
  1990.                     u.done);
  1991.     IF gad = NIL THEN EXIT END;
  1992.  
  1993.     win := I.OpenWindowTagsA(NIL,
  1994.                               I.waLeft,        0,
  1995.                               I.waTop,         8,
  1996.                               I.waInnerWidth,  290,
  1997.                               I.waInnerHeight, 106,
  1998.                               I.waTitle,       SYS.ADR(MuchText),
  1999.                               I.waFlags,       LONGSET{I.activate,I.windowDrag,I.windowDepth,I.simpleRefresh,I.rmbTrap},
  2000.                               I.waIDCMP,       gt.listViewIDCMP+gt.buttonIDCMP+LONGSET{I.gadgetUp,I.refreshWindow},
  2001.                               I.waCustomScreen,pub,
  2002.                               I.waGadgets,     glist,
  2003.                               u.done);
  2004.     IF win = NIL THEN EXIT END;
  2005.     gt.RefreshWindow(win, NIL);
  2006.  
  2007.     dispID := displayID;
  2008.     terminated := f;
  2009.  
  2010.     WHILE ~terminated DO
  2011.       e.WaitPort(win.userPort);
  2012.       LOOP
  2013.         IF terminated THEN EXIT END;
  2014.         imsg := gt.GetIMsg(win.userPort);
  2015.         IF imsg=NIL THEN EXIT END;
  2016.         gad := imsg.iAddress;
  2017.   
  2018.         IF I.gadgetUp IN imsg.class THEN
  2019.           CASE gad.gadgetID OF
  2020.           | gadBUTTONSave:   result := 1; displayID := dispID; terminated := w;
  2021.           | gadBUTTONUse:    result := 2; displayID := dispID; terminated := w;
  2022.           | gadBUTTONCancel: terminated := w;
  2023.           | gadLISTVIEW:     node := GetNode(lvlist,imsg.code);
  2024.                              IF node # NIL THEN dispID := node.displayID END;
  2025.           ELSE
  2026.           END;
  2027.         END;
  2028.   
  2029.         IF I.refreshWindow IN imsg.class THEN
  2030.           gt.BeginRefresh(win);
  2031.           gt.EndRefresh(win, I.LTRUE);
  2032.         END;
  2033.  
  2034.         gt.ReplyIMsg(imsg);
  2035.   
  2036.       END;
  2037.     END;
  2038.  
  2039.     EXIT
  2040.   END;
  2041.  
  2042.   IF win   # NIL THEN I.CloseWindow(win) END;
  2043.   IF glist # NIL THEN gt.FreeGadgets(glist) END;
  2044.   IF vi    # NIL THEN gt.FreeVisualInfo(vi) END;
  2045.   IF pub   # NIL THEN I.UnlockPubScreen(NIL,pub) END;
  2046.  
  2047.   RETURN result;
  2048. END ScreenModeReq;
  2049.  
  2050.  
  2051. (*-------------------------------------------------------------------------*)
  2052.  
  2053.  
  2054. PROCEDURE SavePrefs;
  2055.  
  2056. VAR
  2057.   lock: d.FileLockPtr;
  2058.  
  2059.   PROCEDURE SavePrefsName(name: StringPtr);
  2060.   VAR file: d.FileHandlePtr;
  2061.       l: LONGINT;
  2062.   BEGIN
  2063.     file := d.Open(name^,d.newFile);
  2064.     IF file # NIL THEN
  2065.       SYS.SETREG(0,d.Write(file,"FORM",4));
  2066.       l := 16;
  2067.       SYS.SETREG(0,d.Write(file,l,4));
  2068.       SYS.SETREG(0,d.Write(file,"MUMO",4));
  2069.       SYS.SETREG(0,d.Write(file,"DPID",4));
  2070.       l := 4;
  2071.       SYS.SETREG(0,d.Write(file,l,4));
  2072.       SYS.SETREG(0,d.Write(file,id,4));
  2073.       d.OldClose(file);
  2074.     END;
  2075.   END SavePrefsName;
  2076.  
  2077. BEGIN
  2078.   IF DirExists("ENV:") THEN
  2079.     IF ~DirExists("ENV:MuchMore") THEN
  2080.       lock := d.CreateDir("ENV:MuchMore");
  2081.       IF lock#NIL THEN d.UnLock(lock) END;
  2082.     END;
  2083.     SavePrefsName(SYS.ADR("ENV:MuchMore/MuchMore.prefs"))
  2084.   END;
  2085.   IF DirExists("ENVARC:") THEN
  2086.     IF ~DirExists("ENVARC:MuchMore") THEN
  2087.       lock := d.CreateDir("ENVARC:MuchMore");
  2088.       IF lock#NIL THEN d.UnLock(lock) END;
  2089.     END;
  2090.     SavePrefsName(SYS.ADR("ENVARC:MuchMore/MuchMore.prefs"))
  2091.   END;
  2092. END SavePrefs;
  2093.  
  2094.  
  2095. (*-------------------------------------------------------------------------*)
  2096.  
  2097.  
  2098. PROCEDURE LoadPrefs;
  2099.  
  2100. VAR file: d.FileHandlePtr;
  2101.     l,i,s: LONGINT;
  2102.     ok: BOOLEAN;
  2103.  
  2104. BEGIN
  2105.   file := NIL;
  2106.   IF DirExists("PROGDIR:") THEN
  2107.     file := d.Open("PROGDIR:MuchMore.prefs",d.oldFile);
  2108.   END;
  2109.   IF (file=NIL) & DirExists("ENV:") THEN
  2110.     file := d.Open("ENV:MuchMore/MuchMore.prefs",d.oldFile);
  2111.   END;
  2112.   IF file # NIL THEN
  2113.     LOOP
  2114.       IF (d.Read(file,i,4) <= 0)        OR
  2115.          (i # SYS.VAL(LONGINT,"FORM"))  OR
  2116.          (d.Read(file,s,4) <= 0)        OR
  2117.          (d.Read(file,i,4) <= 0)        OR
  2118.          (i # SYS.VAL(LONGINT,"MUMO"))    THEN EXIT END;
  2119.       WHILE w DO
  2120.         IF (d.Read(file,i,4) <= 0)      OR
  2121.            (d.Read(file,s,4) <= 0)        THEN EXIT END;
  2122.         IF ODD(s) THEN INC(s) END;
  2123.         IF (s=4) & (i=SYS.VAL(LONGINT,"DPID")) THEN
  2124.           SYS.SETREG(0,d.Read(file,id,4));
  2125.         ELSE
  2126.           IF s < 0 THEN EXIT END;
  2127.           SYS.SETREG(0,d.Seek(file,s,d.current));
  2128.         END;
  2129.       END;
  2130.  
  2131.       EXIT;
  2132.     END;
  2133.     d.OldClose(file);
  2134.   END;
  2135. END LoadPrefs;
  2136.  
  2137.  
  2138. (*------------------------  Get Tooltypes:  --------------------------*)
  2139.  
  2140.  
  2141. PROCEDURE EvalIcon(icon: DiskObjectPtr);
  2142. VAR tt: StringPtr;
  2143.  
  2144. BEGIN
  2145.   IF icon # NIL THEN
  2146.     tt := FindToolType(icon.toolTypes,"COLORS");     IF (tt # NIL) THEN COPY(tt^,Pens) END;
  2147.     tt := FindToolType(icon.toolTypes,"EXTRASPACE"); IF (tt # NIL) THEN spacing := SHORT(StrToInt(tt,10)) END;
  2148.     tt := FindToolType(icon.toolTypes,"FONT");       IF (tt # NIL) THEN COPY(tt^,FontName) END;
  2149.     tt := FindToolType(icon.toolTypes,"NOOSCAN");    IF (tt # NIL) & (MatchToolValue(tt^,"TRUE")) THEN noOscan := w END;
  2150.     tt := FindToolType(icon.toolTypes,"ONEPLANE");   IF (tt # NIL) & (MatchToolValue(tt^,"TRUE")) THEN onePlane := w END;
  2151.     tt := FindToolType(icon.toolTypes,"PASSWORD");   IF (tt # NIL) THEN COPY(tt^,Password) END;
  2152.     tt := FindToolType(icon.toolTypes,"SCROLLMODE"); IF (tt # NIL) THEN scrollmode := SHORT(StrToInt(tt,10)) END;
  2153.     tt := FindToolType(icon.toolTypes,"TABWIDTH");   IF (tt # NIL) THEN tabw := SHORT(StrToInt(tt,10)) END;
  2154.     tt := FindToolType(icon.toolTypes,"TOGGLELACE"); IF (tt # NIL) & (MatchToolValue(tt^,"TRUE")) THEN lace := ~lace END;
  2155.     tt := FindToolType(icon.toolTypes,"TOOLPRI");    IF (tt # NIL) THEN taskpri := SHORT(SHORT(StrToInt(tt,10))) END;
  2156.     FreeDiskObject(icon);
  2157.   END;
  2158. END EvalIcon;
  2159.  
  2160.  
  2161. (*------------------------------  MAIN:  ----------------------------------*)
  2162.  
  2163. BEGIN
  2164.  
  2165. (*------  Init:  ------*)
  2166.  
  2167.   ol.OutOfMemHandler := OutOfMemHandler;
  2168.  
  2169.   mySigBit := -1; Me := SYS.VAL(d.ProcessPtr,ol.Me);
  2170.   WriteName := "PRT:"; MemIndex := ChunkSize; OldDir := Me.currentDir;
  2171.   oldpri := Me.task.node.pri;
  2172.   taskpri := oldpri;
  2173.   Sync := w;
  2174.   FontSize := 8;
  2175.   Pattern := "~(#?.info)";
  2176.   id := g.invalidID;
  2177.   tabw := 8;
  2178.   IF g.gfx.libNode.version >= 37 THEN scrollmode := 1 END;
  2179.  
  2180.  
  2181.   I.GetPrefs(Prefs,SIZE(Prefs));
  2182.   lace := Prefs.laceWB # SHORTSET{};
  2183.  
  2184.   mySigBit := e.AllocSignal(-1);
  2185.   IF mySigBit<0 THEN HALT(0) END;
  2186.   mySig := LONGSET{mySigBit};
  2187.  
  2188.   iconBase := e.OpenLibrary("icon.library",33);
  2189.  
  2190. (*------  Setup:  ------*)
  2191.  
  2192.   NEW(FirstLine);
  2193. (*FirstLine.size := 0;
  2194.   FirstLine.text[0] := 0X; *)
  2195.  
  2196. (*------  Start:  ------*)
  2197.  
  2198.   LoadPrefs;
  2199.  
  2200.   IF ol.wbStarted THEN
  2201.  
  2202.     wbm := ol.wbenchMsg;
  2203.     IF iconBase # NIL THEN
  2204.       oldLace:=lace;
  2205.       j := SHORT(wbm.numArgs); IF j>2 THEN j := 2 END;
  2206.       FOR i := 0 TO j-1 DO
  2207.         lace := oldLace;
  2208.         SYS.SETREG(0,d.CurrentDir(wbm.argList[i].lock));
  2209.         nameptr := wbm.argList[i].name;
  2210.         icon := GetDiskObject(nameptr^);
  2211.         IF (icon=NIL) & (d.base.lib.version >= 37) THEN
  2212.           SYS.SETREG(0,d.CurrentDir(d.GetProgramDir()));
  2213.           icon := GetDiskObject(nameptr^);
  2214.         END;
  2215.         EvalIcon(icon);
  2216.       END;
  2217.     END; (* IF iconBase#NIL *)
  2218.  
  2219.     IF wbm.numArgs >= 2 THEN
  2220.       ArgPtr := wbm.argList^[1].name; Name := ArgPtr^;
  2221.       SYS.SETREG(0,d.CurrentDir(wbm.argList^[1].lock));
  2222.     ELSE
  2223.       SYS.SETREG(0,d.CurrentDir(wbm.argList^[0].lock));
  2224.       FileReq(Name)
  2225.     END;
  2226.  
  2227.   ELSE
  2228.  
  2229.     IF d.dos.lib.version < 37 THEN
  2230.       IF ol.dosCmdLen > 1 THEN
  2231.         CommLine := ol.dosCmdBuf;
  2232.         j := 0;
  2233.         LOOP
  2234.           i := 0;
  2235.           WHILE CommLine[j]=20X DO INC(j) END;
  2236.           IF CommLine[j]=0AX THEN EXIT END;
  2237.           IF CommLine[j]='"' THEN
  2238.             INC(j);
  2239.             LOOP
  2240.               CASE CommLine[j] OF
  2241.               | '"': INC(j); EXIT
  2242.               | 0AX:                     EXIT
  2243.               ELSE
  2244.                 option[i] := CommLine[j]; INC(i); INC(j);
  2245.               END;
  2246.             END;
  2247.           ELSE
  2248.             WHILE (CommLine[j]#0AX) & (CommLine[j]#20X) DO
  2249.               option[i] := CommLine[j]; INC(i); INC(j);
  2250.             END;
  2251.           END;
  2252.           option[i]:= 0X;
  2253.           IF option="?"  THEN Request(usage) END;
  2254.           IF option[0]="-" THEN
  2255.             CASE CAP(option[1]) OF
  2256.               "A": tabw := SHORT(StrToInt(SYS.ADR(option[2]),10)) |
  2257.               "C": GetStr(SYS.ADR(option[2]),Pens) |
  2258.               "E": spacing := SHORT(StrToInt(SYS.ADR(option[2]),10)) |
  2259.               "F": GetStr(SYS.ADR(option[2]),FontName) |
  2260.               "L": lace := ~lace |
  2261.               "O": onePlane := w |
  2262.               "P": GetStr(SYS.ADR(option[2]),Password) |
  2263.               "S": scrollmode := SHORT(StrToInt(SYS.ADR(option[2]),10)) |
  2264.               "T": taskpri := SHORT(SHORT(StrToInt(SYS.ADR(option[2]),10))) |
  2265.             ELSE
  2266.               Request(usage);
  2267.             END;
  2268.           ELSE
  2269.             COPY(option,Name);
  2270.           END;
  2271.         END;
  2272.       END;
  2273.  
  2274.     ELSE  (* d.dos.lib.version >= 37 *)
  2275.  
  2276.       IF iconBase#NIL THEN
  2277.         oldcd := d.CurrentDir(d.GetProgramDir());
  2278.         IF d.GetProgramName(Name,LEN(Name)) THEN
  2279.           icon := GetDiskObject(Name);
  2280.           EvalIcon(icon);
  2281.           Name[0] := 0X;
  2282.         END;
  2283.         oldcd := d.CurrentDir(oldcd);
  2284.       END;
  2285.  
  2286.       rd := d.ReadArgs("A=TABWIDTH/N/K,C=COLORS/K,D=DISPMODEREQ/S,E=EXTRASPACE/N/K,F=FONT/K,N=NOOSCAN/S,O=ONEPLANE/S,P=PASSWORD/K,S=SCROLLMODE/N/K,T=TOOLPRI/N/K,FILE",args,NIL);
  2287.       IF rd=NIL THEN
  2288.         SYS.SETREG(0,d.PrintFault(d.IoErr(),NIL));
  2289.         HALT(d.warn)
  2290.       END;
  2291.       IF args.a # NIL THEN tabw := SHORT(args.a^) END;
  2292.       IF args.c # NIL THEN COPY(args.c^,Pens) END;
  2293.       IF args.d # NIL THEN modeReq := w END;
  2294.       IF args.e # NIL THEN spacing := SHORT(args.e^) END;
  2295.       IF args.f # NIL THEN COPY(args.f^,FontName) END;
  2296.       IF args.n # NIL THEN noOscan := w END;
  2297.       IF args.o # NIL THEN onePlane := w END;
  2298.       IF args.p # NIL THEN COPY(args.p^,Password) END;
  2299.       IF args.s # NIL THEN scrollmode := SHORT(args.s^) END;
  2300.       IF args.t # NIL THEN taskpri := SHORT(SHORT(args.t^)) END;
  2301.       IF args.file # NIL THEN COPY(args.file^,Name) END;
  2302.       d.FreeArgs(rd); rd := NIL;
  2303.     END;
  2304.   END;
  2305.  
  2306.   IF tabw <  1 THEN tabw :=  1 END;
  2307.  
  2308.   IF taskpri#oldpri THEN SYS.SETREG(0,e.SetTaskPri(Me,taskpri)) END;
  2309.  
  2310.   IF FontName[0]#0X THEN
  2311.     i := 0;
  2312.     j := SHORT(str.Length(FontName));
  2313.     LOOP
  2314.       IF i >= j THEN EXIT END;
  2315.       IF FontName[i]='/' THEN
  2316.         FontName[i] := 0X;
  2317.         FontSize := SHORT(StrToInt(SYS.ADR(FontName[i+1]),10));
  2318.         j := i;
  2319.         EXIT
  2320.       END;
  2321.       INC(i);
  2322.     END;
  2323.     IF j<LEN(FontName)-6 THEN
  2324.       e.CopyMem(".font",FontName[j],6);
  2325.     END;
  2326.   END;
  2327.  
  2328.   IF FontSize>50 THEN FontSize := 50 END;
  2329.   IF FontSize< 5 THEN FontSize :=  5 END;
  2330.  
  2331.   IF spacing< 0 THEN spacing :=  0 END;
  2332.   IF spacing>20 THEN spacing := 20 END;
  2333.  
  2334.   IF modeReq & (gt.base#NIL) THEN
  2335.     IF ScreenModeReq(id) = 1 THEN SavePrefs END;
  2336.   END;
  2337.  
  2338. (*------  Open File:  ------*)
  2339.  
  2340.   LOOP
  2341.     MyFile := d.Open(Name,d.oldFile);
  2342.     IF MyFile#NIL THEN EXIT END;
  2343.     FileReq(Name)
  2344.   END;
  2345.  
  2346. (*------------------------  Open Display:  --------------------------------*)
  2347.  
  2348. (*------  Open Screen:  ------*)
  2349.  
  2350.   IF lace THEN
  2351.     NuScreen.viewModes := {g.hires,g.lace};
  2352.     NuScreen.height := g.gfx.normalDisplayRows*2
  2353.   ELSE
  2354.     NuScreen.viewModes := {g.hires};
  2355.     NuScreen.height := g.gfx.normalDisplayRows
  2356.   END;
  2357.   NuScreen.width  := g.gfx.normalDisplayColumns;
  2358.   NuScreen.depth  := 2;
  2359.   NuScreen.type   := I.customScreen+{I.screenQuiet};
  2360.  
  2361.   IF onePlane THEN NuScreen.depth := 1; END;
  2362.  
  2363.   LOOP
  2364.  
  2365.     IF I.int.libNode.version >= 37 THEN
  2366.  
  2367.       IF id=g.invalidID THEN
  2368.         id := g.defaultMonitorID;
  2369.         pub := I.LockPubScreen("Workbench");
  2370.         IF pub # NIL THEN
  2371.           id := g.GetVPModeID(SYS.ADR(pub.viewPort));
  2372.           I.UnlockPubScreen(NIL,pub);
  2373.         END;
  2374.       END;
  2375.  
  2376.       IF g.GetDisplayInfoData(NIL,dims,SIZE(dims),g.dtagDims,id) > 0 THEN
  2377.         IF noOscan THEN
  2378.           NuScreen.width     := dims.nominal.maxX - dims.nominal.minX + 1;
  2379.           NuScreen.height    := dims.nominal.maxY - dims.nominal.minY + 1;
  2380.           overscanTag := u.ignore;
  2381.         ELSE
  2382.           NuScreen.width     := dims.txtOScan.maxX - dims.txtOScan.minX + 1;
  2383.           NuScreen.height    := dims.txtOScan.maxY - dims.txtOScan.minY + 1;
  2384.           overscanTag := I.saOverscan;
  2385.         END;
  2386.         IF g.GetDisplayInfoData(NIL,disp,SIZE(disp),g.dtagDisp,id) > 0 THEN
  2387.           lace := g.isLace IN disp.propertyFlags;
  2388.           Scrollable := (g.isDraggable IN disp.propertyFlags) (* & ((g.gfx.libNode.version<39) OR ~(20 IN disp.propertyFlags)) *);
  2389.           IF scrollmode=3 THEN Scrollable := f END;
  2390.           IF Scrollable THEN INC(NuScreen.height,NuScreen.height) END;
  2391.  
  2392.           Screen := I.OpenScreenTags(NuScreen,
  2393.                                      I.saDisplayID,id,
  2394.                                      overscanTag,I.oScanText,
  2395.                                      I.saPens,SYS.ADR("\xFF\xFF"),
  2396.                                   (* saInterleaved,I.LFALSE, *)
  2397.                                      u.end);
  2398.         END;
  2399.       END;
  2400.  
  2401.     ELSE
  2402.  
  2403.       Scrollable := w;
  2404.       IF scrollmode=3 THEN Scrollable := f END;
  2405.       IF Scrollable THEN INC(NuScreen.height,NuScreen.height) END;
  2406.       Screen := I.OpenScreen(NuScreen);
  2407.  
  2408.     END;
  2409.  
  2410.     IF Screen#NIL THEN EXIT END;
  2411.  
  2412.     DEC(NuScreen.depth);
  2413.     IF NuScreen.depth=0 THEN Request(cos) END;
  2414.   END;
  2415.  
  2416.   IF NuScreen.depth=1 THEN onePlane := w END;
  2417.  
  2418.   rp := SYS.ADR(Screen.rastPort);
  2419.   BM := rp.bitMap;
  2420.  
  2421.  
  2422.   IF Pens[0]#0X THEN
  2423.     i := 0;
  2424.     chptr := SYS.ADR(Pens);
  2425.     Pens[LEN(Pens)-1] := 0X;
  2426.     LOOP
  2427.       Cols[i] := SHORT(StrToInt(SYS.VAL(StringPtr,chptr),16));
  2428.       INC(i); IF i=4 THEN EXIT END;
  2429.       WHILE (chptr^#0X) & (chptr^#",") DO
  2430.         chptr:=SYS.VAL(e.APTR,SYS.VAL(LONGINT,chptr)+1)
  2431.       END;
  2432.       IF chptr^="," THEN
  2433.         chptr:=SYS.VAL(e.APTR,SYS.VAL(LONGINT,chptr)+1)
  2434.       ELSE
  2435.         EXIT
  2436.       END;
  2437.     END;
  2438.     g.LoadRGB4(SYS.ADR(Screen.viewPort),Cols,i);
  2439.   END;
  2440.  
  2441.   IF FontName[0]#0X THEN
  2442.     MyAttr.name := SYS.ADR(FontName);
  2443.     MyAttr.ySize := FontSize;
  2444.     IF diskFontBase=NIL THEN diskFontBase := e.OpenLibrary("diskfont.library",33) END;
  2445.     IF diskFontBase#NIL THEN MyFont := OpenDiskFont(MyAttr) END;
  2446.     IF (MyFont#NIL) & ~(g.proportional IN MyFont.flags) THEN g.SetFont(rp,MyFont) END;
  2447.   END;
  2448.  
  2449.   LOOP
  2450.     fontWidth  := rp.font.xSize;
  2451.     fontHeight := rp.font.ySize;
  2452.     IF (fontWidth<=50) OR (fontHeight<=50) & (fontWidth>2) & (fontHeight>2) THEN EXIT END;
  2453.     MyAttr.name := SYS.ADR("topaz.font");
  2454.     MyAttr.ySize := 8;
  2455.     MyFont := g.OpenFont(MyAttr);
  2456.     IF MyFont=NIL THEN HALT(0) END;
  2457.     g.SetFont(rp,MyFont);
  2458.   END;
  2459.   INC(fontHeight,spacing);               (* extra spacing *)
  2460.   fontBaseLine := rp.font.baseline;
  2461.   NumColumns := Screen.width DIV fontWidth;
  2462.   IF Scrollable THEN NumLines   := Screen.height DIV 2 DIV fontHeight;
  2463.                 ELSE NumLines   := Screen.height DIV fontHeight; END;
  2464.   LineSize   := LONG(fontHeight)*BM.bytesPerRow;
  2465.   PageSize   := LineSize*NumLines;
  2466.   PageHeight := fontHeight*NumLines;
  2467.  
  2468.   NuScreen.height := fontHeight*NumLines;
  2469.   NuScreen.width  := Screen.width;
  2470.  
  2471.   IF Scrollable THEN
  2472.     (*
  2473.     IF NuScreen.depth=1 THEN BM.planes[1] := BM.planes[0] END;
  2474.     *)
  2475.     ri := Screen.viewPort.rasInfo;
  2476.     ClearBitMaps;
  2477.     ri.ryOffset := 32;
  2478.     Screen.height := NuScreen.height;
  2479.     I.MakeScreen(Screen);
  2480.     I.RethinkDisplay;
  2481.   END;
  2482.  
  2483. (*------  Open Window:  ------*)
  2484.  
  2485.   NuWindow.flags  := LONGSET{I.rmbTrap,I.activate,I.borderless};
  2486.   NuWindow.screen := Screen;
  2487.   NuWindow.type   := I.customScreen;
  2488.   NuWindow.topEdge:= 10;
  2489.   NuWindow.width  := Screen.width;
  2490.   NuWindow.height := Screen.height-10;
  2491.   NuWindow.idcmpFlags := MyIdcmp;
  2492.   Window := I.OpenWindow(NuWindow);
  2493.   IF Window=NIL THEN Request(cow) END;
  2494.   ClearBitMaps;
  2495.  
  2496. (*------  Get KeyMap:  ------*)
  2497.  
  2498.   IF e.OpenDevice("console.device",-1,SYS.ADR(wreq),LONGSET{})#0 THEN Request(conerr) END;
  2499.   console := wreq.device;
  2500. (*ievent.nextEvent := NIL;
  2501.   ievent.qualifier := {};
  2502.   ievent.eventAddress := NIL; *)
  2503.   ievent.class := ie.rawkey;
  2504.  
  2505.   FOR i := 0 TO 3FH DO
  2506.     ievent.code := i;
  2507.     RawKeyConvert(SYS.ADR(ievent),SYS.ADR(KeyMap[i]),10H,NIL);
  2508.   END;
  2509.  
  2510. (*------  Decrunch:  ------*)
  2511.  
  2512.   Decrunch;
  2513.  
  2514. (*------  Init 2nd Task:  ------*)
  2515.  
  2516.   ShowTask.spLower := SYS.ADR(ShowStack);
  2517.   ShowTask.spUpper := SYS.ADR(ShowStack[1000]);
  2518.   ShowTask.spReg   := ShowTask.spUpper;
  2519.   ShowTask.node.type := e.task;
  2520.   ShowTask.node.name := SYS.ADR("Show.MM");
  2521.   ShowTask.node.pri  := Me.task.node.pri+1;
  2522.   (* $IF SmallData *)
  2523.   ShowTask.userData  := SYS.REG(13);           (* VarBase *)
  2524.   (* $END *)
  2525.  
  2526.   e.Forbid;
  2527.     e.AddTask(SYS.ADR(ShowTask),ShowProc,NIL);
  2528.     ShowTaskRunning := w;
  2529.     Window.userPort.sigTask := SYS.ADR(ShowTask);
  2530.   e.Permit;
  2531.  
  2532. (*------  Main Load / Display Loop:  ------*)
  2533.  
  2534.   LOOP
  2535.  
  2536.     fg := 1; bg := 0; style := SHORTSET{};
  2537.     RQLen := -1; RQPos := -1;
  2538.     AnzLines := 1;
  2539.     LastLine := FirstLine;
  2540.     BottomLine := FirstLine;
  2541.     TopLine    := FirstLine;
  2542.     TextLength := 0;
  2543.     FindLine   := NIL;
  2544.     FOR i := 0 TO 9 DO TextMarkers[i] := NIL END;
  2545.  
  2546.     MyLock := d.Lock(Name,d.sharedLock);
  2547.     IF MyLock=NIL THEN Request(cof) END;
  2548.     IF ~ d.Examine(MyLock,FileInfo) THEN Request(cof) END;
  2549.     FileLength := FileInfo.size;
  2550.  
  2551.     d.UnLock(MyLock); MyLock := NIL;
  2552.     IF FileLength=0 THEN Request("File empty") END;
  2553.  
  2554.     (*------  Start displaying & Loading:  ------*)
  2555.  
  2556.     NewDisp := w;
  2557.  
  2558.     e.Signal(SYS.ADR(ShowTask),mySig);
  2559.  
  2560.     REPEAT
  2561.       LoadLine := GetTextLine();
  2562.       IF LoadLine=NIL THEN
  2563.         d.OldClose(MyFile);
  2564.         MyFile := NIL;
  2565.       ELSE
  2566.         LoadLine.prev := LastLine;
  2567.         LastLine.next := LoadLine;
  2568.         LastLine := LoadLine;
  2569.       END;
  2570.       IF SignalNewData THEN e.Signal(SYS.ADR(ShowTask),mySig) END;
  2571.     UNTIL (MyFile=NIL) OR Done OR NewText;
  2572.     IF SignalAllRead THEN e.Signal(SYS.ADR(ShowTask),mySig) END;
  2573.     REPEAT
  2574.       SYS.SETREG(0,e.Wait(mySig));
  2575.       IF print THEN
  2576.         in := d.Open("NIL:",d.oldFile); out := d.Open("NIL:",d.newFile);
  2577.         SYS.SETREG(0,d.Execute(PStr,in,out));
  2578.         d.OldClose(in); in := NIL; d.OldClose(out); out := NIL; print := f;
  2579.       END;
  2580.       IF save THEN
  2581.         in := d.Open(Name,d.oldFile);
  2582.         IF in=NIL THEN I.DisplayBeep(NIL) ELSE
  2583.           ol.New(buffer,savesize);
  2584.           SYS.SETREG(0,d.Seek(in,savefrom,0));
  2585.           IF d.Read(in,buffer^,savesize)#savesize THEN
  2586.             I.DisplayBeep(NIL); d.OldClose(in); in := NIL;
  2587.           ELSE
  2588.             d.OldClose(in); in := NIL;
  2589.             out := d.Open(WriteName,d.newFile);
  2590.             IF out=NIL THEN I.DisplayBeep(NIL) ELSE
  2591.               IF d.Write(out,buffer^,savesize)#savesize THEN I.DisplayBeep(NIL) END;
  2592.               d.OldClose(out); out := NIL;
  2593.             END;
  2594.           END;
  2595.           DISPOSE(buffer);
  2596.         END;
  2597.         save := f;
  2598.       END;
  2599.       IF Done THEN EXIT END;
  2600.     UNTIL NewText;
  2601.     IF MyFile#NIL THEN d.OldClose(MyFile); MyFile := NIL END;
  2602.     IF Decrunched & d.DeleteFile(Name) THEN END;
  2603.     Decrunched := f;
  2604.     DisposeLines();
  2605.     FirstLine^.next := NIL; NewText := f;
  2606.     Name := OldName;
  2607.     REPEAT
  2608.       FileReq(Name);
  2609.       MyFile := d.Open(Name,d.oldFile);
  2610.     UNTIL MyFile#NIL;
  2611.     Decrunch;
  2612.   END;   (* LOOP *)
  2613.  
  2614. CLOSE
  2615.  
  2616.   IF win         #NIL THEN I.CloseWindow(win)                   END;
  2617.   IF ShowTaskRunning  THEN e.RemTask(SYS.ADR(ShowTask))         END;
  2618.   IF console     #NIL THEN e.CloseDevice(SYS.ADR(wreq))         END;
  2619.   IF Window      #NIL THEN I.CloseWindow(Window)                END;
  2620.   IF Screen      #NIL THEN d.Delay(2); I.OldCloseScreen(Screen) END;
  2621.   IF MyFont      #NIL THEN g.CloseFont(MyFont)                  END;
  2622.   IF MyFile      #NIL THEN d.OldClose(MyFile)                   END;
  2623.   IF in          #NIL THEN d.OldClose(in)                       END;
  2624.   IF out         #NIL THEN d.OldClose(out)                      END;
  2625.   IF Decrunched       THEN SYS.SETREG(0,d.DeleteFile(Name))     END;
  2626.   IF MyLock      #NIL THEN d.UnLock(MyLock)                     END;
  2627.   IF xpk         #NIL THEN e.CloseLibrary(xpk)                  END;
  2628.   IF arp         #NIL THEN e.CloseLibrary(arp)                  END;
  2629.   IF asl         #NIL THEN e.CloseLibrary(asl)                  END;
  2630.   IF diskFontBase#NIL THEN e.CloseLibrary(diskFontBase)         END;
  2631.   IF iconBase    #NIL THEN e.CloseLibrary(iconBase)             END;
  2632.   IF rd          #NIL THEN d.FreeArgs(rd)                       END;
  2633.   IF mySigBit>=0      THEN e.FreeSignal(mySigBit)               END;
  2634.   IF taskpri  #oldpri THEN oldpri := e.SetTaskPri(Me,oldpri)    END;
  2635.   OldDir := d.CurrentDir(OldDir);
  2636.  
  2637. END MuchMore.
  2638.  
  2639.